From 87edb1d45e3558043aff8258d5c86fb17e4a4f16 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 7 Mar 2024 13:09:58 +0300 Subject: [PATCH 01/11] GL-related refactor --- src/assets/assetload_funcs.cpp | 16 +++-- src/frontend/BlocksPreview.cpp | 6 +- src/frontend/WorldRenderer.cpp | 10 ++-- src/frontend/graphics/Skybox.cpp | 28 ++++----- src/frontend/graphics/Skybox.h | 8 ++- src/frontend/gui/containers.cpp | 3 +- src/frontend/gui/controls.cpp | 5 +- src/frontend/hud.cpp | 8 +-- src/graphics/Framebuffer.cpp | 56 +++++++++++++----- src/graphics/Framebuffer.h | 11 +++- src/graphics/GfxContext.cpp | 97 ++++++++++++++++++++++--------- src/graphics/GfxContext.h | 26 +++++---- src/graphics/Shader.h | 3 +- src/graphics/Texture.cpp | 22 +++++-- src/graphics/Texture.h | 24 +++++--- src/graphics/TextureAnimation.cpp | 12 ++-- 16 files changed, 224 insertions(+), 111 deletions(-) diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index 2b9b752d..aae0a8f6 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -136,7 +136,7 @@ bool assetload::font( } pages.push_back(std::move(texture)); } - int res = pages[0]->height / 16; + int res = pages[0]->getHeight() / 16; assets->store(new Font(std::move(pages), res, 4), name); return true; } @@ -270,13 +270,19 @@ static bool animation( Frame frame; UVRegion region = dstAtlas->get(name); - frame.dstPos = glm::ivec2(region.u1 * dstTex->width, region.v1 * dstTex->height); - frame.size = glm::ivec2(region.u2 * dstTex->width, region.v2 * dstTex->height) - frame.dstPos; + uint dstWidth = dstTex->getWidth(); + uint dstHeight = dstTex->getHeight(); + + uint srcWidth = srcTex->getWidth(); + uint srcHeight = srcTex->getHeight(); + + frame.dstPos = glm::ivec2(region.u1 * dstWidth, region.v1 * dstHeight); + frame.size = glm::ivec2(region.u2 * dstWidth, region.v2 * dstHeight) - frame.dstPos; if (frameList.empty()) { for (const auto& elem : builder.getNames()) { region = srcAtlas->get(elem); - frame.srcPos = glm::ivec2(region.u1 * srcTex->width, srcTex->height - region.v2 * srcTex->height); + frame.srcPos = glm::ivec2(region.u1 * srcWidth, srcHeight - region.v2 * srcHeight); animation.addFrame(frame); } } @@ -288,7 +294,7 @@ static bool animation( } region = srcAtlas->get(elem.first); frame.duration = elem.second; - frame.srcPos = glm::ivec2(region.u1 * srcTex->width, srcTex->height - region.v2 * srcTex->height); + frame.srcPos = glm::ivec2(region.u1 * srcWidth, srcHeight - region.v2 * srcHeight); animation.addFrame(frame); } } diff --git a/src/frontend/BlocksPreview.cpp b/src/frontend/BlocksPreview.cpp index dd487b2f..3f3291c9 100644 --- a/src/frontend/BlocksPreview.cpp +++ b/src/frontend/BlocksPreview.cpp @@ -95,7 +95,7 @@ ImageData* BlocksPreview::draw( break; } } - return fbo->texture->readData(); + return fbo->getTexture()->readData(); } std::unique_ptr BlocksPreview::build( @@ -113,8 +113,8 @@ std::unique_ptr BlocksPreview::build( Viewport viewport(iconSize, iconSize); GfxContext pctx(nullptr, viewport, nullptr); GfxContext ctx = pctx.sub(); - ctx.cullFace(true); - ctx.depthTest(true); + ctx.setCullFace(true); + ctx.setDepthTest(true); Framebuffer fbo(iconSize, iconSize, true); Batch3D batch(1024); diff --git a/src/frontend/WorldRenderer.cpp b/src/frontend/WorldRenderer.cpp index ed1744ab..3dbb86f4 100644 --- a/src/frontend/WorldRenderer.cpp +++ b/src/frontend/WorldRenderer.cpp @@ -159,8 +159,8 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible Shader* linesShader = assets->getShader("lines"); { GfxContext ctx = pctx.sub(); - ctx.depthTest(true); - ctx.cullFace(true); + ctx.setDepthTest(true); + ctx.setCullFace(true); float fogFactor = 15.0f / ((float)settings.chunks.loadDistance-2); @@ -224,7 +224,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible if (hudVisible && player->debug) { GfxContext ctx = pctx.sub(); - ctx.depthTest(true); + ctx.setDepthTest(true); linesShader->use(); @@ -248,14 +248,14 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible 0.f, (float)displayHeight, -length, length) * model * glm::inverse(camera->rotation)); - ctx.depthTest(false); + ctx.setDepthTest(false); lineBatch->lineWidth(4.0f); lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 1.f); lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 1.f); lineBatch->render(); - ctx.depthTest(true); + ctx.setDepthTest(true); lineBatch->lineWidth(2.0f); lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f); lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 1.f); diff --git a/src/frontend/graphics/Skybox.cpp b/src/frontend/graphics/Skybox.cpp index cb481990..fd98e3d3 100644 --- a/src/frontend/graphics/Skybox.cpp +++ b/src/frontend/graphics/Skybox.cpp @@ -8,6 +8,8 @@ #include "../../graphics/Shader.h" #include "../../graphics/Mesh.h" #include "../../graphics/Batch3D.h" +#include "../../graphics/Texture.h" +#include "../../graphics/Framebuffer.h" #include "../../window/Window.h" #include "../../window/Camera.h" @@ -19,9 +21,9 @@ const int STARS_COUNT = 3000; const int STARS_SEED = 632; Skybox::Skybox(uint size, Shader* shader) - : size(size), - shader(shader), - batch3d(new Batch3D(4096)) + : size(size), + shader(shader), + batch3d(std::make_unique(4096)) { glGenTextures(1, &cubemap); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); @@ -33,7 +35,10 @@ Skybox::Skybox(uint size, Shader* shader) for (uint face = 0; face < 6; face++) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); } - glGenFramebuffers(1, &fbo); + + uint fboid; + glGenFramebuffers(1, &fboid); + fbo = std::make_unique(fboid, 0, (std::unique_ptr)nullptr); float vertices[] { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, @@ -59,7 +64,6 @@ Skybox::Skybox(uint size, Shader* shader) Skybox::~Skybox() { glDeleteTextures(1, &cubemap); - glDeleteFramebuffers(1, &fbo); } void Skybox::drawBackground(Camera* camera, Assets* assets, int width, int height) { @@ -109,7 +113,7 @@ void Skybox::draw( drawBackground(camera, assets, width, height); GfxContext ctx = pctx.sub(); - ctx.blendMode(blendmode::addition); + ctx.setBlendMode(blendmode::addition); Shader* shader = assets->getShader("ui3d"); shader->use(); @@ -141,15 +145,15 @@ void Skybox::draw( void Skybox::refresh(const GfxContext& pctx, float t, float mie, uint quality) { GfxContext ctx = pctx.sub(); - ctx.depthMask(false); - ctx.depthTest(false); + ctx.setDepthMask(false); + ctx.setDepthTest(false); + ctx.setFramebuffer(fbo.get()); + ctx.setViewport(Viewport(size, size)); ready = true; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); shader->use(); - Window::viewport(0,0, size, size); const glm::vec3 xaxs[] = { {0.0f, 0.0f, -1.0f}, @@ -194,8 +198,6 @@ void Skybox::refresh(const GfxContext& pctx, float t, float mie, uint quality) { } glBindTexture(GL_TEXTURE_CUBE_MAP, 0); glActiveTexture(GL_TEXTURE0); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - Window::viewport(0, 0, Window::width, Window::height); } void Skybox::bind() const { @@ -208,4 +210,4 @@ void Skybox::unbind() const { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); glActiveTexture(GL_TEXTURE0); -} \ No newline at end of file +} diff --git a/src/frontend/graphics/Skybox.h b/src/frontend/graphics/Skybox.h index 163b0b7f..14f2cddd 100644 --- a/src/frontend/graphics/Skybox.h +++ b/src/frontend/graphics/Skybox.h @@ -13,6 +13,7 @@ class Shader; class Assets; class Camera; class Batch3D; +class Framebuffer; struct skysprite { std::string texture; @@ -22,7 +23,7 @@ struct skysprite { }; class Skybox { - uint fbo; + std::unique_ptr fbo; uint cubemap; uint size; Shader* shader; @@ -44,7 +45,8 @@ public: Camera* camera, Assets* assets, float daytime, - float fog); + float fog + ); void refresh(const GfxContext& pctx, float t, float mie, uint quality); void bind() const; @@ -54,4 +56,4 @@ public: } }; -#endif // FRONTEND_GRAPHICS_SKYBOX_H_ \ No newline at end of file +#endif // FRONTEND_GRAPHICS_SKYBOX_H_ diff --git a/src/frontend/gui/containers.cpp b/src/frontend/gui/containers.cpp index f908dc85..9f89d2f8 100644 --- a/src/frontend/gui/containers.cpp +++ b/src/frontend/gui/containers.cpp @@ -88,12 +88,11 @@ void Container::draw(const GfxContext* pctx, Assets* assets) { batch->flush(); { GfxContext ctx = pctx->sub(); - ctx.scissors(glm::vec4(pos.x, pos.y, size.x, size.y)); + ctx.setScissors(glm::vec4(pos.x, pos.y, size.x, size.y)); for (auto node : nodes) { if (node->isVisible()) node->draw(pctx, assets); } - batch->flush(); } } diff --git a/src/frontend/gui/controls.cpp b/src/frontend/gui/controls.cpp index d6e2b413..5ad500e4 100644 --- a/src/frontend/gui/controls.cpp +++ b/src/frontend/gui/controls.cpp @@ -204,7 +204,7 @@ void Image::draw(const GfxContext* pctx, Assets* assets) { auto texture = assets->getTexture(this->texture); if (texture && autoresize) { - setSize(glm::vec2(texture->width, texture->height)); + setSize(glm::vec2(texture->getWidth(), texture->getHeight())); } batch->texture(texture); batch->setColor(color); @@ -383,7 +383,7 @@ void TextBox::draw(const GfxContext* pctx, Assets* assets) { glm::vec2 size = getSize(); auto subctx = pctx->sub(); - subctx.scissors(glm::vec4(pos.x, pos.y, size.x, size.y)); + subctx.setScissors(glm::vec4(pos.x, pos.y, size.x, size.y)); const int lineHeight = font->getLineHeight() * label->getLineInterval(); glm::vec2 lcoord = label->calcPos(); @@ -418,7 +418,6 @@ void TextBox::draw(const GfxContext* pctx, Assets* assets) { batch->rect(lcoord.x, lcoord.y+label->getLineYOffset(endLine), end, lineHeight); } } - batch->flush(); } void TextBox::drawBackground(const GfxContext* pctx, Assets* assets) { diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index d7cf2d7a..3215980f 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -481,18 +481,16 @@ void Hud::draw(const GfxContext& ctx){ // Crosshair if (!pause && !inventoryOpen && !player->debug) { GfxContext chctx = ctx.sub(); - chctx.blendMode(blendmode::inversion); + chctx.setBlendMode(blendmode::inversion); auto texture = assets->getTexture("gui/crosshair"); batch->texture(texture); - int chsizex = texture != nullptr ? texture->width : 16; - int chsizey = texture != nullptr ? texture->height : 16; + int chsizex = texture != nullptr ? texture->getWidth() : 16; + int chsizey = texture != nullptr ? texture->getHeight() : 16; batch->rect( (width-chsizex)/2, (height-chsizey)/2, chsizex, chsizey, 0,0, 1,1, 1,1,1,1 ); - batch->flush(); } - batch->flush(); } void Hud::updateElementsPosition(const Viewport& viewport) { diff --git a/src/graphics/Framebuffer.cpp b/src/graphics/Framebuffer.cpp index d5f38398..e70b3628 100644 --- a/src/graphics/Framebuffer.cpp +++ b/src/graphics/Framebuffer.cpp @@ -3,38 +3,66 @@ #include #include "Texture.h" +Framebuffer::Framebuffer(uint fbo, uint depth, std::unique_ptr texture) + : fbo(fbo), depth(depth), texture(std::move(texture)) +{ + if (texture) { + width = texture->getWidth(); + height = texture->getHeight(); + } else { + width = 0; + height = 0; + } +} + Framebuffer::Framebuffer(uint width, uint height, bool alpha) - : width(width), height(height) { - glGenFramebuffers(1, &fbo); - bind(); - GLuint tex; - glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); + : width(width), height(height) +{ + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // Setup color attachment (texture) + GLuint tex; GLuint format = alpha ? GL_RGBA : GL_RGB; - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, nullptr); + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); - texture = new Texture(tex, width, height); + texture = std::make_unique(tex, width, height); + + // Setup depth attachment glGenRenderbuffers(1, &depth); glBindRenderbuffer(GL_RENDERBUFFER, depth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth); - unbind(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } Framebuffer::~Framebuffer() { - delete texture; - glDeleteFramebuffers(1, &fbo); + glDeleteFramebuffers(1, &fbo); glDeleteRenderbuffers(1, &depth); } void Framebuffer::bind() { - glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); } void Framebuffer::unbind() { - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} \ No newline at end of file + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +Texture* Framebuffer::getTexture() const { + return texture.get(); +} + +uint Framebuffer::getWidth() const { + return width; +} + +uint Framebuffer::getHeight() const { + return height; +} diff --git a/src/graphics/Framebuffer.h b/src/graphics/Framebuffer.h index e6111244..d5bf7a74 100644 --- a/src/graphics/Framebuffer.h +++ b/src/graphics/Framebuffer.h @@ -3,20 +3,27 @@ #include "../typedefs.h" +#include + class Texture; class Framebuffer { uint fbo; uint depth; -public: uint width; uint height; - Texture* texture; + std::unique_ptr texture; +public: + Framebuffer(uint fbo, uint depth, std::unique_ptr texture); Framebuffer(uint width, uint height, bool alpha=false); ~Framebuffer(); void bind(); void unbind(); + + Texture* getTexture() const; + uint getWidth() const; + uint getHeight() const; }; #endif /* SRC_GRAPHICS_FRAMEBUFFER_H_ */ diff --git a/src/graphics/GfxContext.cpp b/src/graphics/GfxContext.cpp index 3367bc1d..dc3b8ee1 100644 --- a/src/graphics/GfxContext.cpp +++ b/src/graphics/GfxContext.cpp @@ -3,10 +3,16 @@ #include #include "Batch2D.h" +#include "Framebuffer.h" -GfxContext::GfxContext(const GfxContext* parent, Viewport& viewport, Batch2D* g2d) - : parent(parent), viewport(viewport), g2d(g2d) { -} +GfxContext::GfxContext( + const GfxContext* parent, + const Viewport& viewport, + Batch2D* g2d +) : parent(parent), + viewport(viewport), + g2d(g2d) +{} GfxContext::~GfxContext() { while (scissorsCount--) { @@ -15,20 +21,39 @@ GfxContext::~GfxContext() { if (parent == nullptr) return; - - if (depthMask_ != parent->depthMask_) { - glDepthMask(parent->depthMask_); + + if (g2d) { + g2d->flush(); } - if (depthTest_ != parent->depthTest_) { - if (depthTest_) glDisable(GL_DEPTH_TEST); + + if (fbo != parent->fbo) { + if (fbo) { + fbo->unbind(); + } + if (parent->fbo) { + fbo->bind(); + } + } + + Window::viewport( + 0, 0, + parent->viewport.getWidth(), + parent->viewport.getHeight() + ); + + if (depthMask != parent->depthMask) { + glDepthMask(parent->depthMask); + } + if (depthTest != parent->depthTest) { + if (depthTest) glDisable(GL_DEPTH_TEST); else glEnable(GL_DEPTH_TEST); } - if (cullFace_ != parent->cullFace_) { - if (cullFace_) glDisable(GL_CULL_FACE); + if (cullFace != parent->cullFace) { + if (cullFace) glDisable(GL_CULL_FACE); else glEnable(GL_CULL_FACE); } - if (blendMode_ != parent->blendMode_) { - Window::setBlendMode(parent->blendMode_); + if (blendMode != parent->blendMode) { + Window::setBlendMode(parent->blendMode); } } @@ -42,22 +67,40 @@ Batch2D* GfxContext::getBatch2D() const { GfxContext GfxContext::sub() const { auto ctx = GfxContext(this, viewport, g2d); - ctx.depthTest_ = depthTest_; - ctx.cullFace_ = cullFace_; + ctx.depthTest = depthTest; + ctx.cullFace = cullFace; return ctx; } -void GfxContext::depthMask(bool flag) { - if (depthMask_ == flag) +void GfxContext::setViewport(const Viewport& viewport) { + this->viewport = viewport; + Window::viewport( + 0, 0, + viewport.getWidth(), + viewport.getHeight() + ); +} + +void GfxContext::setFramebuffer(Framebuffer* fbo) { + if (this->fbo == fbo) return; - depthMask_ = flag; + this->fbo = fbo; + if (fbo) { + fbo->bind(); + } +} + +void GfxContext::setDepthMask(bool flag) { + if (depthMask == flag) + return; + depthMask = flag; glDepthMask(GL_FALSE + flag); } -void GfxContext::depthTest(bool flag) { - if (depthTest_ == flag) +void GfxContext::setDepthTest(bool flag) { + if (depthTest == flag) return; - depthTest_ = flag; + depthTest = flag; if (flag) { glEnable(GL_DEPTH_TEST); } else { @@ -65,10 +108,10 @@ void GfxContext::depthTest(bool flag) { } } -void GfxContext::cullFace(bool flag) { - if (cullFace_ == flag) +void GfxContext::setCullFace(bool flag) { + if (cullFace == flag) return; - cullFace_ = flag; + cullFace = flag; if (flag) { glEnable(GL_CULL_FACE); } else { @@ -76,14 +119,14 @@ void GfxContext::cullFace(bool flag) { } } -void GfxContext::blendMode(blendmode mode) { - if (blendMode_ == mode) +void GfxContext::setBlendMode(blendmode mode) { + if (blendMode == mode) return; - blendMode_ = mode; + blendMode = mode; Window::setBlendMode(mode); } -void GfxContext::scissors(glm::vec4 area) { +void GfxContext::setScissors(glm::vec4 area) { Window::pushScissor(area); scissorsCount++; } diff --git a/src/graphics/GfxContext.h b/src/graphics/GfxContext.h index c2cc0824..3590d4a1 100644 --- a/src/graphics/GfxContext.h +++ b/src/graphics/GfxContext.h @@ -6,29 +6,33 @@ #include "../window/Window.h" class Batch2D; +class Framebuffer; class GfxContext { const GfxContext* parent; - Viewport& viewport; + Viewport viewport; Batch2D* const g2d; - bool depthMask_ = true; - bool depthTest_ = false; - bool cullFace_ = false; - blendmode blendMode_ = blendmode::normal; + Framebuffer* fbo = nullptr; + bool depthMask = true; + bool depthTest = false; + bool cullFace = false; + blendmode blendMode = blendmode::normal; int scissorsCount = 0; public: - GfxContext(const GfxContext* parent, Viewport& viewport, Batch2D* g2d); + GfxContext(const GfxContext* parent, const Viewport& viewport, Batch2D* g2d); ~GfxContext(); Batch2D* getBatch2D() const; const Viewport& getViewport() const; GfxContext sub() const; - void depthMask(bool flag); - void depthTest(bool flag); - void cullFace(bool flag); - void blendMode(blendmode mode); - void scissors(glm::vec4 area); + void setViewport(const Viewport& viewport); + void setFramebuffer(Framebuffer* fbo); + void setDepthMask(bool flag); + void setDepthTest(bool flag); + void setCullFace(bool flag); + void setBlendMode(blendmode mode); + void setScissors(glm::vec4 area); }; #endif // GRAPHICS_GFX_CONTEXT_H_ \ No newline at end of file diff --git a/src/graphics/Shader.h b/src/graphics/Shader.h index 3aea4585..851a2806 100644 --- a/src/graphics/Shader.h +++ b/src/graphics/Shader.h @@ -3,13 +3,14 @@ #include #include +#include "../typedefs.h" class GLSLExtension; class Shader { + uint id; public: static GLSLExtension* preprocessor; - unsigned int id; Shader(unsigned int id); ~Shader(); diff --git a/src/graphics/Texture.cpp b/src/graphics/Texture.cpp index a0fbacc0..80a45aef 100644 --- a/src/graphics/Texture.cpp +++ b/src/graphics/Texture.cpp @@ -5,17 +5,19 @@ #include "ImageData.h" -Texture::Texture(uint id, int width, int height) +Texture::Texture(uint id, uint width, uint height) : id(id), width(width), height(height) { } -Texture::Texture(ubyte* data, int width, int height, uint format) +Texture::Texture(ubyte* data, uint width, uint height, uint format) : width(width), height(height) { glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, - format, GL_UNSIGNED_BYTE, (GLvoid *) data); + glTexImage2D( + GL_TEXTURE_2D, 0, format, width, height, 0, + format, GL_UNSIGNED_BYTE, (GLvoid *) data + ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glGenerateMipmap(GL_TEXTURE_2D); @@ -66,3 +68,15 @@ Texture* Texture::from(const ImageData* image) { } return new Texture((ubyte*)data, width, height, format); } + +uint Texture::getWidth() const { + return width; +} + +uint Texture::getHeight() const { + return height; +} + +uint Texture::getId() const { + return id; +} diff --git a/src/graphics/Texture.h b/src/graphics/Texture.h index 8ece550a..571463d7 100644 --- a/src/graphics/Texture.h +++ b/src/graphics/Texture.h @@ -7,20 +7,26 @@ class ImageData; class Texture { -public: +protected: uint id; - int width; - int height; - Texture(uint id, int width, int height); - Texture(ubyte* data, int width, int height, uint format); - ~Texture(); + uint width; + uint height; +public: + Texture(uint id, uint width, uint height); + Texture(ubyte* data, uint width, uint height, uint format); + virtual ~Texture(); - void bind(); - void reload(ubyte* data); + virtual void bind(); + virtual void reload(ubyte* data); void setNearestFilter(); - ImageData* readData(); + virtual ImageData* readData(); + + virtual uint getWidth() const; + virtual uint getHeight() const; + + virtual uint getId() const; static Texture* from(const ImageData* image); }; diff --git a/src/graphics/TextureAnimation.cpp b/src/graphics/TextureAnimation.cpp index 6cdd8484..19baba7a 100644 --- a/src/graphics/TextureAnimation.cpp +++ b/src/graphics/TextureAnimation.cpp @@ -35,19 +35,23 @@ void TextureAnimator::update(float delta) { frame = elem.frames[elem.currentFrame]; } if (frameNum != elem.currentFrame){ - if (changedTextures.find(elem.dstTexture->id) == changedTextures.end()) changedTextures.insert(elem.dstTexture->id); + uint elemDstId = elem.dstTexture->getId(); + uint elemSrcId = elem.srcTexture->getId(); + + if (changedTextures.find(elemDstId) == changedTextures.end()) + changedTextures.insert(elemDstId); glBindFramebuffer(GL_FRAMEBUFFER, fboD); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, elem.dstTexture->id, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, elemDstId, 0); glBindFramebuffer(GL_FRAMEBUFFER, fboR); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, elem.srcTexture->id, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, elemSrcId, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboD); glBindFramebuffer(GL_READ_FRAMEBUFFER, fboR); - float srcPosY = elem.srcTexture->height - frame.size.y - frame.srcPos.y; // vertical flip + float srcPosY = elem.srcTexture->getHeight() - frame.size.y - frame.srcPos.y; // vertical flip // Extensions const int ext = 2; From eefd327845d049a25339cc71ab6d34f9da971eae Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 7 Mar 2024 13:40:38 +0300 Subject: [PATCH 02/11] Cubemap class --- src/frontend/graphics/Skybox.cpp | 29 +++++++++--------------- src/frontend/graphics/Skybox.h | 1 - src/graphics/Batch2D.cpp | 2 +- src/graphics/Batch3D.cpp | 6 ++--- src/graphics/Batch3D.h | 12 ++++++---- src/graphics/Cubemap.cpp | 39 ++++++++++++++++++++++++++++++++ src/graphics/Cubemap.h | 14 ++++++++++++ src/graphics/Texture.cpp | 18 +++++++-------- src/graphics/Texture.h | 6 ++--- src/graphics/gl_util.h | 19 ++++++++++++++++ 10 files changed, 105 insertions(+), 41 deletions(-) create mode 100644 src/graphics/Cubemap.cpp create mode 100644 src/graphics/Cubemap.h create mode 100644 src/graphics/gl_util.h diff --git a/src/frontend/graphics/Skybox.cpp b/src/frontend/graphics/Skybox.cpp index fd98e3d3..2e5d8e06 100644 --- a/src/frontend/graphics/Skybox.cpp +++ b/src/frontend/graphics/Skybox.cpp @@ -9,6 +9,7 @@ #include "../../graphics/Mesh.h" #include "../../graphics/Batch3D.h" #include "../../graphics/Texture.h" +#include "../../graphics/Cubemap.h" #include "../../graphics/Framebuffer.h" #include "../../window/Window.h" #include "../../window/Camera.h" @@ -25,20 +26,11 @@ Skybox::Skybox(uint size, Shader* shader) shader(shader), batch3d(std::make_unique(4096)) { - glGenTextures(1, &cubemap); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - for (uint face = 0; face < 6; face++) { - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - } + auto cubemap = std::make_unique(size, size, ImageFormat::rgb888); uint fboid; glGenFramebuffers(1, &fboid); - fbo = std::make_unique(fboid, 0, (std::unique_ptr)nullptr); + fbo = std::make_unique(fboid, 0, std::move(cubemap)); float vertices[] { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, @@ -63,7 +55,6 @@ Skybox::Skybox(uint size, Shader* shader) } Skybox::~Skybox() { - glDeleteTextures(1, &cubemap); } void Skybox::drawBackground(Camera* camera, Assets* assets, int width, int height) { @@ -150,9 +141,11 @@ void Skybox::refresh(const GfxContext& pctx, float t, float mie, uint quality) { ctx.setFramebuffer(fbo.get()); ctx.setViewport(Viewport(size, size)); + auto cubemap = dynamic_cast(fbo->getTexture()); + ready = true; glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); + cubemap->bind(); shader->use(); const glm::vec3 xaxs[] = { @@ -190,24 +183,24 @@ void Skybox::refresh(const GfxContext& pctx, float t, float mie, uint quality) { shader->uniform1f("u_fog", mie - 1.0f); shader->uniform3f("u_lightDir", glm::normalize(glm::vec3(sin(t), -cos(t), 0.0f))); for (uint face = 0; face < 6; face++) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, cubemap, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, cubemap->getId(), 0); shader->uniform3f("u_xaxis", xaxs[face]); shader->uniform3f("u_yaxis", yaxs[face]); shader->uniform3f("u_zaxis", zaxs[face]); - mesh->draw(GL_TRIANGLES); + mesh->draw(); } - glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + cubemap->unbind(); glActiveTexture(GL_TEXTURE0); } void Skybox::bind() const { glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); + fbo->getTexture()->bind(); glActiveTexture(GL_TEXTURE0); } void Skybox::unbind() const { glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + fbo->getTexture()->unbind(); glActiveTexture(GL_TEXTURE0); } diff --git a/src/frontend/graphics/Skybox.h b/src/frontend/graphics/Skybox.h index 14f2cddd..25e5416e 100644 --- a/src/frontend/graphics/Skybox.h +++ b/src/frontend/graphics/Skybox.h @@ -24,7 +24,6 @@ struct skysprite { class Skybox { std::unique_ptr fbo; - uint cubemap; uint size; Shader* shader; bool ready = false; diff --git a/src/graphics/Batch2D.cpp b/src/graphics/Batch2D.cpp index d576a387..76a8ad31 100644 --- a/src/graphics/Batch2D.cpp +++ b/src/graphics/Batch2D.cpp @@ -19,7 +19,7 @@ Batch2D::Batch2D(size_t capacity) : capacity(capacity), color(1.0f){ ubyte pixels[] = { 0xFF, 0xFF, 0xFF, 0xFF }; - blank = std::make_unique(pixels, 1, 1, GL_RGBA); + blank = std::make_unique(pixels, 1, 1, ImageFormat::rgba8888); _texture = nullptr; } diff --git a/src/graphics/Batch3D.cpp b/src/graphics/Batch3D.cpp index 2def65ef..adacc80e 100644 --- a/src/graphics/Batch3D.cpp +++ b/src/graphics/Batch3D.cpp @@ -19,20 +19,18 @@ Batch3D::Batch3D(size_t capacity) }; buffer = new float[capacity * B3D_VERTEX_SIZE]; - mesh = new Mesh(buffer, 0, attrs); + mesh = std::make_unique(buffer, 0, attrs); index = 0; ubyte pixels[] = { 255, 255, 255, 255, }; - blank = new Texture(pixels, 1, 1, GL_RGBA); + blank = std::make_unique(pixels, 1, 1, ImageFormat::rgba8888); _texture = nullptr; } Batch3D::~Batch3D(){ - delete blank; delete[] buffer; - delete mesh; } void Batch3D::begin(){ diff --git a/src/graphics/Batch3D.h b/src/graphics/Batch3D.h index 771a79ea..dfc3393c 100644 --- a/src/graphics/Batch3D.h +++ b/src/graphics/Batch3D.h @@ -1,21 +1,23 @@ #ifndef GRAPHICS_BATCH3D_H_ #define GRAPHICS_BATCH3D_H_ -#include -#include #include "UVRegion.h" #include "../typedefs.h" +#include +#include +#include + class Mesh; class Texture; class Batch3D { float* buffer; size_t capacity; - Mesh* mesh; + std::unique_ptr mesh; + std::unique_ptr blank; size_t index; - - Texture* blank; + Texture* _texture; void vertex(float x, float y, float z, diff --git a/src/graphics/Cubemap.cpp b/src/graphics/Cubemap.cpp new file mode 100644 index 00000000..f6d0aba1 --- /dev/null +++ b/src/graphics/Cubemap.cpp @@ -0,0 +1,39 @@ +#include "Cubemap.h" +#include "gl_util.h" + +#include + +Cubemap::Cubemap(uint width, uint height, ImageFormat imageFormat) + : Texture(0, width, height) +{ + glGenTextures(1, &id); + glBindTexture(GL_TEXTURE_CUBE_MAP, id); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + uint format = gl::to_gl_format(imageFormat); + for (uint face = 0; face < 6; face++) { + glTexImage2D( + GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, + 0, + format, + width, + height, + 0, + format, + GL_UNSIGNED_BYTE, + NULL + ); + } +} + +void Cubemap::bind(){ + glBindTexture(GL_TEXTURE_CUBE_MAP, id); +} + +void Cubemap::unbind() { + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} diff --git a/src/graphics/Cubemap.h b/src/graphics/Cubemap.h new file mode 100644 index 00000000..7bd41f3c --- /dev/null +++ b/src/graphics/Cubemap.h @@ -0,0 +1,14 @@ +#ifndef GRAPHICS_CUBEMAP_H_ +#define GRAPHICS_CUBEMAP_H_ + +#include "Texture.h" + +class Cubemap : public Texture { +public: + Cubemap(uint width, uint height, ImageFormat format); + + virtual void bind() override; + virtual void unbind() override; +}; + +#endif // GRAPHICS_CUBEMAP_H_ diff --git a/src/graphics/Texture.cpp b/src/graphics/Texture.cpp index 80a45aef..fbebef1f 100644 --- a/src/graphics/Texture.cpp +++ b/src/graphics/Texture.cpp @@ -4,16 +4,19 @@ #include #include "ImageData.h" +#include "gl_util.h" Texture::Texture(uint id, uint width, uint height) : id(id), width(width), height(height) { } -Texture::Texture(ubyte* data, uint width, uint height, uint format) +Texture::Texture(ubyte* data, uint width, uint height, ImageFormat imageFormat) : width(width), height(height) { glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + GLenum format = gl::to_gl_format(imageFormat); glTexImage2D( GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, (GLvoid *) data @@ -33,6 +36,10 @@ void Texture::bind(){ glBindTexture(GL_TEXTURE_2D, id); } +void Texture::unbind() { + glBindTexture(GL_TEXTURE_2D, 0); +} + void Texture::reload(ubyte* data){ glBindTexture(GL_TEXTURE_2D, id); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, @@ -58,15 +65,8 @@ void Texture::setNearestFilter() { Texture* Texture::from(const ImageData* image) { uint width = image->getWidth(); uint height = image->getHeight(); - uint format; const void* data = image->getData(); - switch (image->getFormat()) { - case ImageFormat::rgb888: format = GL_RGB; break; - case ImageFormat::rgba8888: format = GL_RGBA; break; - default: - throw std::runtime_error("unsupported image data format"); - } - return new Texture((ubyte*)data, width, height, format); + return new Texture((ubyte*)data, width, height, image->getFormat()); } uint Texture::getWidth() const { diff --git a/src/graphics/Texture.h b/src/graphics/Texture.h index 571463d7..11f8ef6d 100644 --- a/src/graphics/Texture.h +++ b/src/graphics/Texture.h @@ -3,8 +3,7 @@ #include #include "../typedefs.h" - -class ImageData; +#include "ImageData.h" class Texture { protected: @@ -13,10 +12,11 @@ protected: uint height; public: Texture(uint id, uint width, uint height); - Texture(ubyte* data, uint width, uint height, uint format); + Texture(ubyte* data, uint width, uint height, ImageFormat format); virtual ~Texture(); virtual void bind(); + virtual void unbind(); virtual void reload(ubyte* data); void setNearestFilter(); diff --git a/src/graphics/gl_util.h b/src/graphics/gl_util.h new file mode 100644 index 00000000..5e7e7953 --- /dev/null +++ b/src/graphics/gl_util.h @@ -0,0 +1,19 @@ +#ifndef GRAPHICS_GL_UTIL_H_ +#define GRAPHICS_GL_UTIL_H_ + +#include + +#include "ImageData.h" + +namespace gl { + inline GLenum to_gl_format(ImageFormat imageFormat) { + switch (imageFormat) { + case ImageFormat::rgb888: return GL_RGB; + case ImageFormat::rgba8888: return GL_RGBA; + default: + return 0; + } + } +} + +#endif // GRAPHICS_GL_UTIL_H_ From fcb420c4c707f14e702d0ee4f9d466e9190931c3 Mon Sep 17 00:00:00 2001 From: InfiniteCoder Date: Thu, 7 Mar 2024 22:30:21 +0300 Subject: [PATCH 03/11] Event queue --- res/scripts/stdlib.lua | 20 +++ src/logic/scripting/lua/LuaState.cpp | 30 ++++- src/logic/scripting/lua/LuaState.h | 6 +- src/logic/scripting/lua/libblock.cpp | 2 + src/logic/scripting/scripting.cpp | 137 ++++++++++----------- src/logic/scripting/scripting.h | 4 + src/logic/scripting/scripting_frontend.cpp | 12 +- 7 files changed, 131 insertions(+), 80 deletions(-) diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index 4968b675..50218698 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -120,6 +120,26 @@ function color_mt.__tostring(self) return "rgba("..self[1]..", "..self[2]..", "..self[3]..", "..self[4]..")" end +-- events +events = { + handlers = {} +} + +function events.on(event, func) + events.handlers[event] = events.handlers[event] or {} + table.insert(events.handlers[event], func) +end + +function events.emit(event, ...) + result = nil + if events.handlers[event] then + for _, func in ipairs(events.handlers[event]) do + result = result or func(...) + end + end + return result +end + -- class designed for simple UI-nodes access via properties syntax local Element = {} function Element.new(docname, name) diff --git a/src/logic/scripting/lua/LuaState.cpp b/src/logic/scripting/lua/LuaState.cpp index e7988dd5..e472831d 100644 --- a/src/logic/scripting/lua/LuaState.cpp +++ b/src/logic/scripting/lua/LuaState.cpp @@ -1,5 +1,6 @@ #include "LuaState.h" +#include #include #include "lua_util.h" #include "api_lua.h" @@ -217,8 +218,8 @@ int lua::LuaState::pushnil() { return 1; } -bool lua::LuaState::getfield(const std::string& name) { - lua_getfield(L, -1, name.c_str()); +bool lua::LuaState::getfield(const std::string& name, int idx) { + lua_getfield(L, idx, name.c_str()); if (lua_isnil(L, -1)) { lua_pop(L, -1); return false; @@ -287,3 +288,28 @@ void lua::LuaState::removeEnvironment(int id) { lua_pushnil(L); setglobal(envName(id)); } + +void lua::LuaState::dumpStack() { + int top = gettop(); + for (int i = 1; i <= top; i++) { + std::cout << std::setw(3) << i << std::setw(20) << luaL_typename(L, i) << std::setw(30); + switch (lua_type(L, i)) { + case LUA_TNUMBER: + std::cout << tonumber(i); + break; + case LUA_TSTRING: + std::cout << tostring(i); + break; + case LUA_TBOOLEAN: + std::cout << (toboolean(i) ? "true" : "false"); + break; + case LUA_TNIL: + std::cout << "nil"; + break; + default: + std::cout << lua_topointer(L, i); + break; + } + std::cout << std::endl; + } +} diff --git a/src/logic/scripting/lua/LuaState.h b/src/logic/scripting/lua/LuaState.h index 319ee280..d9a7e49d 100644 --- a/src/logic/scripting/lua/LuaState.h +++ b/src/logic/scripting/lua/LuaState.h @@ -41,8 +41,8 @@ namespace lua { int pushnil(); int pushglobals(); void pop(int n=1); - bool getfield(const std::string& name); - void setfield(const std::string& name, int idx=-2); + bool getfield(const std::string& name, int idx = -1); + void setfield(const std::string& name, int idx = -2); bool toboolean(int idx); luaint tointeger(int idx); luanumber tonumber(int idx); @@ -61,6 +61,8 @@ namespace lua { int createEnvironment(int parent); void removeEnvironment(int id); const std::string storeAnonymous(); + + void dumpStack(); }; } diff --git a/src/logic/scripting/lua/libblock.cpp b/src/logic/scripting/lua/libblock.cpp index 56b3d963..2f0c18a8 100644 --- a/src/logic/scripting/lua/libblock.cpp +++ b/src/logic/scripting/lua/libblock.cpp @@ -228,6 +228,8 @@ const luaL_Reg blocklib [] = { {"get_Z", lua_wrap_errors}, {"get_states", lua_wrap_errors}, {"set_states", lua_wrap_errors}, + {"get_rotation", lua_wrap_errors}, + {"set_rotation", lua_wrap_errors}, {"get_user_bits", lua_wrap_errors}, {"set_user_bits", lua_wrap_errors}, {NULL, NULL} diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index d5bc3e6c..350e2949 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -105,25 +105,19 @@ void scripting::on_world_load(Level* level, BlocksController* blocks) { load_script("world.lua"); for (auto& pack : scripting::engine->getContentPacks()) { - if (state->getglobal(pack.id+".worldopen")) { - state->callNoThrow(0); - } + emit_event(pack.id + ".worldopen"); } } void scripting::on_world_save() { for (auto& pack : scripting::engine->getContentPacks()) { - if (state->getglobal(pack.id+".worldsave")) { - state->callNoThrow(0); - } + emit_event(pack.id + ".worldsave"); } } void scripting::on_world_quit() { for (auto& pack : scripting::engine->getContentPacks()) { - if (state->getglobal(pack.id+".worldquit")) { - state->callNoThrow(0); - } + emit_event(pack.id + ".worldquit"); } if (state->getglobal("__scripts_cleanup")) { state->callNoThrow(0); @@ -134,109 +128,97 @@ void scripting::on_world_quit() { } void scripting::on_blocks_tick(const Block* block, int tps) { - std::string name = block->name+".blockstick"; - if (state->getglobal(name)) { + std::string name = block->name + ".blockstick"; + emit_event(name, [tps] (lua::LuaState* state) { state->pushinteger(tps); - state->callNoThrow(1); - } + return 1; + }); } void scripting::update_block(const Block* block, int x, int y, int z) { - std::string name = block->name+".update"; - if (state->getglobal(name)) { + std::string name = block->name + ".update"; + emit_event(name, [x, y, z] (lua::LuaState* state) { state->pushivec3(x, y, z); - state->callNoThrow(3); - } + return 3; + }); } void scripting::random_update_block(const Block* block, int x, int y, int z) { - std::string name = block->name+".randupdate"; - if (state->getglobal(name)) { + std::string name = block->name + ".randupdate"; + emit_event(name, [x, y, z] (lua::LuaState* state) { state->pushivec3(x, y, z); - state->callNoThrow(3); - } + return 3; + }); } void scripting::on_block_placed(Player* player, const Block* block, int x, int y, int z) { - std::string name = block->name+".placed"; - if (state->getglobal(name)) { + std::string name = block->name + ".placed"; + emit_event(name, [x, y, z, player] (lua::LuaState* state) { state->pushivec3(x, y, z); state->pushinteger(player->getId()); - state->callNoThrow(4); - } + return 4; + }); } void scripting::on_block_broken(Player* player, const Block* block, int x, int y, int z) { - std::string name = block->name+".broken"; - if (state->getglobal(name)) { + std::string name = block->name + ".broken"; + emit_event(name, [x, y, z, player] (lua::LuaState* state) { state->pushivec3(x, y, z); state->pushinteger(player->getId()); - state->callNoThrow(4); - } + return 4; + }); } bool scripting::on_block_interact(Player* player, const Block* block, int x, int y, int z) { - std::string name = block->name+".interact"; - if (state->getglobal(name)) { + std::string name = block->name + ".interact"; + return emit_event(name, [x, y, z, player] (lua::LuaState* state) { state->pushivec3(x, y, z); state->pushinteger(player->getId()); - if (state->callNoThrow(4)) { - return state->toboolean(-1); - } - } - return false; + return 4; + }); } bool scripting::on_item_use(Player* player, const ItemDef* item) { - std::string name = item->name+".use"; - if (state->getglobal(name)) { + std::string name = item->name + ".use"; + return emit_event(name, [player] (lua::LuaState* state) { state->pushinteger(player->getId()); - if (state->callNoThrow(1)) { - return state->toboolean(-1); - } - } - return false; + return 1; + }); } bool scripting::on_item_use_on_block(Player* player, const ItemDef* item, int x, int y, int z) { - std::string name = item->name+".useon"; - if (state->getglobal(name)) { + std::string name = item->name + ".useon"; + return emit_event(name, [x, y, z, player] (lua::LuaState* state) { state->pushivec3(x, y, z); state->pushinteger(player->getId()); - if (state->callNoThrow(4)) { - return state->toboolean(-1); - } - } - return false; + return 4; + }); } bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x, int y, int z) { - std::string name = item->name+".blockbreakby"; - if (state->getglobal(name)) { + std::string name = item->name + ".blockbreakby"; + return emit_event(name, [x, y, z, player] (lua::LuaState* state) { state->pushivec3(x, y, z); state->pushinteger(player->getId()); - if (state->callNoThrow(4)) { - return state->toboolean(-1); - } - } - return false; + return 4; + }); } void scripting::on_ui_open(UiDocument* layout, Inventory* inventory, glm::ivec3 blockcoord) { - std::string name = layout->getId()+".open"; - if (state->getglobal(name)) { + std::string name = layout->getId() + ".open"; + emit_event(name, [inventory, blockcoord] (lua::LuaState* state) { state->pushinteger(inventory == nullptr ? 0 : inventory->getId()); state->pushivec3(blockcoord.x, blockcoord.y, blockcoord.z); - state->callNoThrow(4); - } + return 4; + }); } void scripting::on_ui_close(UiDocument* layout, Inventory* inventory) { - std::string name = layout->getId()+".close"; - if (state->getglobal(name)) { - state->pushinteger(inventory->getId()); - state->callNoThrow(1); - } + std::string name = layout->getId() + ".close"; + emit_event(name, [inventory] (lua::LuaState* state) { + state->pushinteger(inventory == nullptr ? 0 : inventory->getId()); + return 1; + }); } bool scripting::register_event(int env, const std::string& name, const std::string& id) { @@ -244,17 +226,32 @@ bool scripting::register_event(int env, const std::string& name, const std::stri state->pushglobals(); } if (state->getfield(name)) { + state->pop(); + state->getglobal("events"); + state->getfield("on"); + state->pushstring(id); + state->getfield(name, -4); + state->callNoThrow(2); + state->pop(); + // remove previous name state->pushnil(); - state->setfield(name, -3); - // add new global name - state->setglobal(id); - state->pop(); + state->setfield(name); return true; } return false; } +bool scripting::emit_event(const std::string &name, std::function args) { + state->getglobal("events"); + state->getfield("emit"); + state->pushstring(name); + state->callNoThrow(args(state) + 1); + bool result = state->toboolean(-1); + state->pop(2); + return result; +} + void scripting::load_block_script(int env, std::string prefix, fs::path file, block_funcs_set& funcsset) { std::string src = files::read_string(file); std::cout << "loading script " << file.u8string() << std::endl; diff --git a/src/logic/scripting/scripting.h b/src/logic/scripting/scripting.h index b4d8c312..5dbc8878 100644 --- a/src/logic/scripting/scripting.h +++ b/src/logic/scripting/scripting.h @@ -4,6 +4,7 @@ #include "../../delegates.h" +#include "lua/LuaState.h" #include "scripting_functional.h" namespace fs = std::filesystem; @@ -44,6 +45,9 @@ namespace scripting { extern bool register_event(int env, const std::string& name, const std::string& id); + static int noargs(lua::LuaState *) { return 0; } + extern bool emit_event(const std::string& name, std::function args = noargs); + std::unique_ptr create_environment(int parent=0); std::unique_ptr create_pack_environment(const ContentPack& pack); std::unique_ptr create_doc_environment(int parent, const std::string& name); diff --git a/src/logic/scripting/scripting_frontend.cpp b/src/logic/scripting/scripting_frontend.cpp index 25828b70..65ee9ff9 100644 --- a/src/logic/scripting/scripting_frontend.cpp +++ b/src/logic/scripting/scripting_frontend.cpp @@ -22,20 +22,20 @@ void scripting::on_frontend_init(Hud* hud) { scripting::state->openlib("hud", hudlib, 0); for (auto& pack : scripting::engine->getContentPacks()) { - if (state->getglobal(pack.id+".hudopen")) { + emit_event(pack.id + ".hudopen", [&] (lua::LuaState* state) { state->pushinteger(hud->getPlayer()->getId()); - state->callNoThrow(1); - } + return 1; + }); } } void scripting::on_frontend_close() { scripting::hud = nullptr; for (auto& pack : scripting::engine->getContentPacks()) { - if (state->getglobal(pack.id+".hudclose")) { + emit_event(pack.id + ".hudclose", [&] (lua::LuaState* state) { state->pushinteger(hud->getPlayer()->getId()); - state->callNoThrow(1); - } + return 1; + }); } } From 8b949c4c9a4eeae87a66ccfe2f04868260fbd96f Mon Sep 17 00:00:00 2001 From: InfiniteCoder Date: Fri, 8 Mar 2024 00:08:01 +0300 Subject: [PATCH 04/11] Overrides! --- src/content/Content.cpp | 12 ++++----- src/content/ContentLoader.cpp | 30 ++++++++++++++++++---- src/logic/scripting/scripting_frontend.cpp | 2 +- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/content/Content.cpp b/src/content/Content.cpp index 99db7f5c..4a847433 100644 --- a/src/content/Content.cpp +++ b/src/content/Content.cpp @@ -32,8 +32,8 @@ void ContentBuilder::add(ContentPackRuntime* pack) { Block& ContentBuilder::createBlock(std::string id) { auto found = blockDefs.find(id); if (found != blockDefs.end()) { - //return found->second; - throw namereuse_error("name "+id+" is already used", contenttype::item); + return *found->second; + // throw namereuse_error("name "+id+" is already used", contenttype::item); } Block* block = new Block(id); add(block); @@ -43,10 +43,10 @@ Block& ContentBuilder::createBlock(std::string id) { ItemDef& ContentBuilder::createItem(std::string id) { auto found = itemDefs.find(id); if (found != itemDefs.end()) { - if (found->second->generated) { - return *found->second; - } - throw namereuse_error("name "+id+" is already used", contenttype::item); + // if (found->second->generated) { + return *found->second; + // } + // throw namereuse_error("name "+id+" is already used", contenttype::item); } ItemDef* item = new ItemDef(id); add(item); diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 7efced5e..951e522c 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -36,6 +36,19 @@ bool ContentLoader::fixPackIndices(fs::path folder, if (name[0] == '_') continue; detected.push_back(name); + } else if (fs::is_directory(file)) { + std::string space = file.stem().string(); + if (space[0] == '_') + continue; + for (auto entry : fs::directory_iterator(file)) { + fs::path file = entry.path(); + if (fs::is_regular_file(file) && file.extension() == ".json") { + std::string name = file.stem().string(); + if (name[0] == '_') + continue; + detected.push_back(space + ':' + name); + } + } } } } @@ -268,7 +281,7 @@ void ContentLoader::loadBlock(Block& def, std::string full, std::string name) { auto folder = pack->folder; fs::path configFile = folder/fs::path("blocks/"+name+".json"); - loadBlock(def, full, configFile); + if (fs::exists(configFile)) loadBlock(def, full, configFile); fs::path scriptfile = folder/fs::path("scripts/"+def.scriptName+".lua"); if (fs::is_regular_file(scriptfile)) { @@ -280,7 +293,7 @@ void ContentLoader::loadItem(ItemDef& def, std::string full, std::string name) { auto folder = pack->folder; fs::path configFile = folder/fs::path("items/"+name+".json"); - loadItem(def, full, configFile); + if (fs::exists(configFile)) loadItem(def, full, configFile); fs::path scriptfile = folder/fs::path("scripts/"+def.scriptName+".lua"); if (fs::is_regular_file(scriptfile)) { @@ -313,8 +326,11 @@ void ContentLoader::load(ContentBuilder& builder) { if (blocksarr) { for (uint i = 0; i < blocksarr->size(); i++) { std::string name = blocksarr->str(i); - std::string full = pack->id+":"+name; + auto colon = name.find(':'); + std::string full = colon == std::string::npos ? pack->id + ":" + name : name; + if (colon != std::string::npos) name[colon] = '/'; auto& def = builder.createBlock(full); + if (colon != std::string::npos) def.scriptName = name.substr(0, colon) + '/' + def.scriptName; loadBlock(def, full, name); stats.totalBlocks++; if (!def.hidden) { @@ -336,8 +352,12 @@ void ContentLoader::load(ContentBuilder& builder) { if (itemsarr) { for (uint i = 0; i < itemsarr->size(); i++) { std::string name = itemsarr->str(i); - std::string full = pack->id+":"+name; - loadItem(builder.createItem(full), full, name); + auto colon = name.find(':'); + std::string full = colon == std::string::npos ? pack->id + ":" + name : name; + if (colon != std::string::npos) name[colon] = '/'; + auto& def = builder.createItem(full); + if (colon != std::string::npos) def.scriptName = name.substr(0, colon) + '/' + def.scriptName; + loadItem(def, full, name); stats.totalItems++; } } diff --git a/src/logic/scripting/scripting_frontend.cpp b/src/logic/scripting/scripting_frontend.cpp index 65ee9ff9..c36ea409 100644 --- a/src/logic/scripting/scripting_frontend.cpp +++ b/src/logic/scripting/scripting_frontend.cpp @@ -30,13 +30,13 @@ void scripting::on_frontend_init(Hud* hud) { } void scripting::on_frontend_close() { - scripting::hud = nullptr; for (auto& pack : scripting::engine->getContentPacks()) { emit_event(pack.id + ".hudclose", [&] (lua::LuaState* state) { state->pushinteger(hud->getPlayer()->getId()); return 1; }); } + scripting::hud = nullptr; } void scripting::load_hud_script(int env, std::string packid, fs::path file) { From 4b48c7c28c23b4eb9901184e1c6b6f77ceaf6d46 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 8 Mar 2024 11:52:40 +0300 Subject: [PATCH 05/11] docs --- src/frontend/WorldRenderer.cpp | 20 +++++++++++--------- src/graphics/Cubemap.h | 1 + src/graphics/Mesh.h | 11 +++++++++++ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/frontend/WorldRenderer.cpp b/src/frontend/WorldRenderer.cpp index 3dbb86f4..cfd25b56 100644 --- a/src/frontend/WorldRenderer.cpp +++ b/src/frontend/WorldRenderer.cpp @@ -148,6 +148,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible Assets* assets = engine->getAssets(); Atlas* atlas = assets->getAtlas("blocks"); Shader* shader = assets->getShader("main"); + Shader* linesShader = assets->getShader("lines"); const Viewport& viewport = pctx.getViewport(); int displayWidth = viewport.getWidth(); @@ -155,8 +156,8 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible // Drawing background sky plane skybox->draw(pctx, camera, assets, level->getWorld()->daytime, fog); - - Shader* linesShader = assets->getShader("lines"); + + // Actually world render with depth buffer on { GfxContext ctx = pctx.sub(); ctx.setDepthTest(true); @@ -174,16 +175,18 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible shader->uniform1f("u_dayTime", level->world->daytime); shader->uniform3f("u_cameraPos", camera->position); shader->uniform1i("u_cubemap", 1); + + // Light emission when an emissive item is chosen { auto inventory = player->getInventory(); ItemStack& stack = inventory->getSlot(player->getChosenSlot()); - ItemDef* item = indices->getItemDef(stack.getItemId()); - assert(item != nullptr); + auto item = indices->getItemDef(stack.getItemId()); float multiplier = 0.5f; shader->uniform3f("u_torchlightColor", - item->emission[0] / 15.0f * multiplier, - item->emission[1] / 15.0f * multiplier, - item->emission[2] / 15.0f * multiplier); + item->emission[0] / 15.0f * multiplier, + item->emission[1] / 15.0f * multiplier, + item->emission[2] / 15.0f * multiplier + ); shader->uniform1f("u_torchlightDistance", 6.0f); } @@ -196,8 +199,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible // Selected block if (PlayerController::selectedBlockId != -1 && hudVisible){ blockid_t id = PlayerController::selectedBlockId; - Block* block = indices->getBlockDef(id); - assert(block != nullptr); + auto block = indices->getBlockDef(id); const glm::vec3 pos = PlayerController::selectedBlockPosition; const glm::vec3 point = PlayerController::selectedPointPosition; const glm::vec3 norm = PlayerController::selectedBlockNormal; diff --git a/src/graphics/Cubemap.h b/src/graphics/Cubemap.h index 7bd41f3c..164a0167 100644 --- a/src/graphics/Cubemap.h +++ b/src/graphics/Cubemap.h @@ -3,6 +3,7 @@ #include "Texture.h" +/// @brief Cubemap texture class Cubemap : public Texture { public: Cubemap(uint width, uint height, ImageFormat format); diff --git a/src/graphics/Mesh.h b/src/graphics/Mesh.h index 4f274222..322c8625 100644 --- a/src/graphics/Mesh.h +++ b/src/graphics/Mesh.h @@ -21,10 +21,21 @@ public: Mesh(vertexBuffer, vertices, nullptr, 0, attrs) {}; ~Mesh(); + /// @brief Update GL vertex and index buffers data without changing VAO attributes + /// @param vertexBuffer vertex data buffer + /// @param vertices number of vertices in new buffer + /// @param indexBuffer indices buffer + /// @param indices number of values in indices buffer void reload(const float* vertexBuffer, size_t vertices, const int* indexBuffer = nullptr, size_t indices = 0); + + /// @brief Draw mesh with specified primitives type + /// @param primitive primitives type void draw(unsigned int primitive); + + /// @brief Draw mesh as triangles void draw(); + /// @brief Total numbers of alive mesh objects static int meshesCount; }; From 8ed65ca51e7eca35a25642b3a6103e8aa2e8d852 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 8 Mar 2024 21:49:38 +0300 Subject: [PATCH 06/11] post-processing test --- res/shaders/screen.glslf | 13 ++ res/shaders/screen.glslv | 12 ++ src/assets/AssetsLoader.cpp | 1 + src/frontend/WorldRenderer.cpp | 210 +++++++++++++++++--------------- src/frontend/WorldRenderer.h | 3 +- src/graphics/Framebuffer.cpp | 12 +- src/graphics/Framebuffer.h | 39 ++++-- src/graphics/GfxContext.cpp | 2 +- src/graphics/PostProcessing.cpp | 42 +++++++ src/graphics/PostProcessing.h | 37 ++++++ src/graphics/Shader.cpp | 5 + src/graphics/Shader.h | 1 + src/graphics/Viewport.h | 4 +- 13 files changed, 268 insertions(+), 113 deletions(-) create mode 100644 res/shaders/screen.glslf create mode 100644 res/shaders/screen.glslv create mode 100644 src/graphics/PostProcessing.cpp create mode 100644 src/graphics/PostProcessing.h diff --git a/res/shaders/screen.glslf b/res/shaders/screen.glslf new file mode 100644 index 00000000..a3bb7ff9 --- /dev/null +++ b/res/shaders/screen.glslf @@ -0,0 +1,13 @@ +in vec2 v_coord; +out vec4 f_color; + +uniform sampler2D u_texture0; +uniform float u_timer; + +void main(){ + vec2 coord = v_coord; + coord.x += sin(u_timer*5.0+coord.x*4.0) * 0.02; + coord.y += cos(u_timer*5.0+coord.y*4.0) * 0.02; + f_color = texture(u_texture0, coord); +} + diff --git a/res/shaders/screen.glslv b/res/shaders/screen.glslv new file mode 100644 index 00000000..772e5f06 --- /dev/null +++ b/res/shaders/screen.glslv @@ -0,0 +1,12 @@ +layout (location = 0) in vec2 v_position; + +out vec2 v_coord; + +uniform ivec2 u_screenSize; +uniform float u_timer; + +void main(){ + v_coord = v_position * 0.5 + 0.5; + gl_Position = vec4(v_position, 0.0, 1.0); +} + diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index 16bf1afc..fe837533 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -74,6 +74,7 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) { loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/cross.png", "gui/cross"); if (content) { loader.add(ASSET_SHADER, SHADERS_FOLDER"/ui3d", "ui3d"); + loader.add(ASSET_SHADER, SHADERS_FOLDER"/screen", "screen"); loader.add(ASSET_SHADER, SHADERS_FOLDER"/background", "background"); loader.add(ASSET_SHADER, SHADERS_FOLDER"/skybox_gen", "skybox_gen"); loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/misc/moon.png", "misc/moon"); diff --git a/src/frontend/WorldRenderer.cpp b/src/frontend/WorldRenderer.cpp index cfd25b56..69888891 100644 --- a/src/frontend/WorldRenderer.cpp +++ b/src/frontend/WorldRenderer.cpp @@ -14,6 +14,7 @@ #include "../graphics/Batch3D.h" #include "../graphics/Texture.h" #include "../graphics/LineBatch.h" +#include "../graphics/PostProcessing.h" #include "../voxels/Chunks.h" #include "../voxels/Chunk.h" #include "../voxels/Block.h" @@ -39,6 +40,7 @@ WorldRenderer::WorldRenderer(Engine* engine, LevelFrontend* frontend, Player* pl level(frontend->getLevel()), player(player) { + postProcessing = std::make_unique(); frustumCulling = std::make_unique(); lineBatch = std::make_unique(); renderer = std::make_unique( @@ -139,8 +141,6 @@ void WorldRenderer::drawChunks(Chunks* chunks, Camera* camera, Shader* shader) { void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible){ EngineSettings& settings = engine->getSettings(); - - Window::clearDepth(); skybox->refresh(pctx, level->world->daytime, 1.0f+fog*2.0f, 4); const Content* content = level->content; @@ -153,116 +153,136 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible const Viewport& viewport = pctx.getViewport(); int displayWidth = viewport.getWidth(); int displayHeight = viewport.getHeight(); - - // Drawing background sky plane - skybox->draw(pctx, camera, assets, level->getWorld()->daytime, fog); - // Actually world render with depth buffer on + // World render scope with diegetic HUD included { - GfxContext ctx = pctx.sub(); - ctx.setDepthTest(true); - ctx.setCullFace(true); + GfxContext wctx = pctx.sub(); + postProcessing->use(wctx); - float fogFactor = 15.0f / ((float)settings.chunks.loadDistance-2); + Window::clearDepth(); - // Setting up main shader - shader->use(); - shader->uniformMatrix("u_proj", camera->getProjection()); - shader->uniformMatrix("u_view", camera->getView()); - shader->uniform1f("u_gamma", settings.graphics.gamma); - shader->uniform1f("u_fogFactor", fogFactor); - shader->uniform1f("u_fogCurve", settings.graphics.fogCurve); - shader->uniform1f("u_dayTime", level->world->daytime); - shader->uniform3f("u_cameraPos", camera->position); - shader->uniform1i("u_cubemap", 1); - - // Light emission when an emissive item is chosen + // Drawing background sky plane + skybox->draw(pctx, camera, assets, level->getWorld()->daytime, fog); + + // Actually world render with depth buffer on { - auto inventory = player->getInventory(); - ItemStack& stack = inventory->getSlot(player->getChosenSlot()); - auto item = indices->getItemDef(stack.getItemId()); - float multiplier = 0.5f; - shader->uniform3f("u_torchlightColor", - item->emission[0] / 15.0f * multiplier, - item->emission[1] / 15.0f * multiplier, - item->emission[2] / 15.0f * multiplier - ); - shader->uniform1f("u_torchlightDistance", 6.0f); + GfxContext ctx = wctx.sub(); + ctx.setDepthTest(true); + ctx.setCullFace(true); + + float fogFactor = 15.0f / ((float)settings.chunks.loadDistance-2); + + // Setting up main shader + shader->use(); + shader->uniformMatrix("u_proj", camera->getProjection()); + shader->uniformMatrix("u_view", camera->getView()); + shader->uniform1f("u_gamma", settings.graphics.gamma); + shader->uniform1f("u_fogFactor", fogFactor); + shader->uniform1f("u_fogCurve", settings.graphics.fogCurve); + shader->uniform1f("u_dayTime", level->world->daytime); + shader->uniform3f("u_cameraPos", camera->position); + shader->uniform1i("u_cubemap", 1); + + // Light emission when an emissive item is chosen + { + auto inventory = player->getInventory(); + ItemStack& stack = inventory->getSlot(player->getChosenSlot()); + auto item = indices->getItemDef(stack.getItemId()); + float multiplier = 0.5f; + shader->uniform3f("u_torchlightColor", + item->emission[0] / 15.0f * multiplier, + item->emission[1] / 15.0f * multiplier, + item->emission[2] / 15.0f * multiplier + ); + shader->uniform1f("u_torchlightDistance", 6.0f); + } + + // Binding main shader textures + skybox->bind(); + atlas->getTexture()->bind(); + + drawChunks(level->chunks.get(), camera, shader); + + // Selected block + if (PlayerController::selectedBlockId != -1 && hudVisible){ + blockid_t id = PlayerController::selectedBlockId; + auto block = indices->getBlockDef(id); + const glm::vec3 pos = PlayerController::selectedBlockPosition; + const glm::vec3 point = PlayerController::selectedPointPosition; + const glm::vec3 norm = PlayerController::selectedBlockNormal; + + std::vector& hitboxes = block->rotatable + ? block->rt.hitboxes[PlayerController::selectedBlockStates] + : block->hitboxes; + + linesShader->use(); + linesShader->uniformMatrix("u_projview", camera->getProjView()); + lineBatch->lineWidth(2.0f); + for (auto& hitbox: hitboxes) { + const glm::vec3 center = pos + hitbox.center(); + const glm::vec3 size = hitbox.size(); + lineBatch->box(center, size + glm::vec3(0.02), glm::vec4(0.f, 0.f, 0.f, 0.5f)); + if (player->debug) { + lineBatch->line(point, point+norm*0.5f, glm::vec4(1.0f, 0.0f, 1.0f, 1.0f)); + } + } + lineBatch->render(); + } + skybox->unbind(); } - // Binding main shader textures - skybox->bind(); - atlas->getTexture()->bind(); - - drawChunks(level->chunks.get(), camera, shader); - - // Selected block - if (PlayerController::selectedBlockId != -1 && hudVisible){ - blockid_t id = PlayerController::selectedBlockId; - auto block = indices->getBlockDef(id); - const glm::vec3 pos = PlayerController::selectedBlockPosition; - const glm::vec3 point = PlayerController::selectedPointPosition; - const glm::vec3 norm = PlayerController::selectedBlockNormal; - - std::vector& hitboxes = block->rotatable - ? block->rt.hitboxes[PlayerController::selectedBlockStates] - : block->hitboxes; + if (hudVisible && player->debug) { + GfxContext ctx = pctx.sub(); + ctx.setDepthTest(true); linesShader->use(); - linesShader->uniformMatrix("u_projview", camera->getProjView()); - lineBatch->lineWidth(2.0f); - for (auto& hitbox: hitboxes) { - const glm::vec3 center = pos + hitbox.center(); - const glm::vec3 size = hitbox.size(); - lineBatch->box(center, size + glm::vec3(0.02), glm::vec4(0.f, 0.f, 0.f, 0.5f)); - if (player->debug) { - lineBatch->line(point, point+norm*0.5f, glm::vec4(1.0f, 0.0f, 1.0f, 1.0f)); - } + + if (settings.debug.showChunkBorders){ + linesShader->uniformMatrix("u_projview", camera->getProjView()); + glm::vec3 coord = player->camera->position; + if (coord.x < 0) coord.x--; + if (coord.z < 0) coord.z--; + int cx = floordiv((int)coord.x, CHUNK_W); + int cz = floordiv((int)coord.z, CHUNK_D); + + drawBorders(cx * CHUNK_W, 0, cz * CHUNK_D, + (cx + 1) * CHUNK_W, CHUNK_H, (cz + 1) * CHUNK_D); } + + float length = 40.f; + glm::vec3 tsl(displayWidth/2, displayHeight/2, 0.f); + glm::mat4 model(glm::translate(glm::mat4(1.f), tsl)); + linesShader->uniformMatrix("u_projview", glm::ortho( + 0.f, (float)displayWidth, + 0.f, (float)displayHeight, + -length, length) * model * glm::inverse(camera->rotation)); + + ctx.setDepthTest(false); + lineBatch->lineWidth(4.0f); + lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); + lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 1.f); + lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 1.f); + lineBatch->render(); + + ctx.setDepthTest(true); + lineBatch->lineWidth(2.0f); + lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f); + lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 1.f); + lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 1.f); lineBatch->render(); } - skybox->unbind(); } - if (hudVisible && player->debug) { + { GfxContext ctx = pctx.sub(); - ctx.setDepthTest(true); - - linesShader->use(); - - if (settings.debug.showChunkBorders){ - linesShader->uniformMatrix("u_projview", camera->getProjView()); - glm::vec3 coord = player->camera->position; - if (coord.x < 0) coord.x--; - if (coord.z < 0) coord.z--; - int cx = floordiv((int)coord.x, CHUNK_W); - int cz = floordiv((int)coord.z, CHUNK_D); - - drawBorders(cx * CHUNK_W, 0, cz * CHUNK_D, - (cx + 1) * CHUNK_W, CHUNK_H, (cz + 1) * CHUNK_D); - } - - float length = 40.f; - glm::vec3 tsl(displayWidth/2, displayHeight/2, 0.f); - glm::mat4 model(glm::translate(glm::mat4(1.f), tsl)); - linesShader->uniformMatrix("u_projview", glm::ortho( - 0.f, (float)displayWidth, - 0.f, (float)displayHeight, - -length, length) * model * glm::inverse(camera->rotation)); - ctx.setDepthTest(false); - lineBatch->lineWidth(4.0f); - lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); - lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 1.f); - lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 1.f); - lineBatch->render(); + + auto shader = assets->getShader("screen"); + shader->use(); + shader->uniform1f("u_timer", Window::time()); + shader->uniform1f("u_dayTime", level->world->daytime); - ctx.setDepthTest(true); - lineBatch->lineWidth(2.0f); - lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f); - lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 1.f); - lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 1.f); - lineBatch->render(); + postProcessing->render(ctx, shader); } } diff --git a/src/frontend/WorldRenderer.h b/src/frontend/WorldRenderer.h index 2359f139..7c56c3e7 100644 --- a/src/frontend/WorldRenderer.h +++ b/src/frontend/WorldRenderer.h @@ -20,17 +20,18 @@ class Batch3D; class LineBatch; class ChunksRenderer; class Shader; -class Texture; class Frustum; class Engine; class Chunks; class LevelFrontend; class Skybox; +class PostProcessing; class WorldRenderer { Engine* engine; Level* level; Player* player; + std::unique_ptr postProcessing; std::unique_ptr frustumCulling; std::unique_ptr lineBatch; std::unique_ptr renderer; diff --git a/src/graphics/Framebuffer.cpp b/src/graphics/Framebuffer.cpp index e70b3628..7e19c4f5 100644 --- a/src/graphics/Framebuffer.cpp +++ b/src/graphics/Framebuffer.cpp @@ -23,7 +23,7 @@ Framebuffer::Framebuffer(uint width, uint height, bool alpha) // Setup color attachment (texture) GLuint tex; - GLuint format = alpha ? GL_RGBA : GL_RGB; + format = alpha ? GL_RGBA : GL_RGB; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, nullptr); @@ -55,6 +55,16 @@ void Framebuffer::unbind() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } +void Framebuffer::resize(uint width, uint height) { + if (this->width == width && this->height == height) { + return; + } + GLuint texid = texture->getId(); + texture->bind(); + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, nullptr); + texture->unbind(); +} + Texture* Framebuffer::getTexture() const { return texture.get(); } diff --git a/src/graphics/Framebuffer.h b/src/graphics/Framebuffer.h index d5bf7a74..65680504 100644 --- a/src/graphics/Framebuffer.h +++ b/src/graphics/Framebuffer.h @@ -8,22 +8,35 @@ class Texture; class Framebuffer { - uint fbo; - uint depth; - uint width; - uint height; - std::unique_ptr texture; + uint fbo; + uint depth; + uint width; + uint height; + uint format; + std::unique_ptr texture; public: - Framebuffer(uint fbo, uint depth, std::unique_ptr texture); - Framebuffer(uint width, uint height, bool alpha=false); - ~Framebuffer(); + Framebuffer(uint fbo, uint depth, std::unique_ptr texture); + Framebuffer(uint width, uint height, bool alpha=false); + ~Framebuffer(); - void bind(); - void unbind(); + /// @brief Use framebuffer + void bind(); - Texture* getTexture() const; - uint getWidth() const; - uint getHeight() const; + /// @brief Stop using framebuffer + void unbind(); + + /// @brief Update framebuffer texture size + /// @param width new width + /// @param height new height + void resize(uint width, uint height); + + /// @brief Get framebuffer color attachment + Texture* getTexture() const; + + /// @brief Get framebuffer width + uint getWidth() const; + /// @brief Get framebuffer height + uint getHeight() const; }; #endif /* SRC_GRAPHICS_FRAMEBUFFER_H_ */ diff --git a/src/graphics/GfxContext.cpp b/src/graphics/GfxContext.cpp index dc3b8ee1..57557942 100644 --- a/src/graphics/GfxContext.cpp +++ b/src/graphics/GfxContext.cpp @@ -31,7 +31,7 @@ GfxContext::~GfxContext() { fbo->unbind(); } if (parent->fbo) { - fbo->bind(); + parent->fbo->bind(); } } diff --git a/src/graphics/PostProcessing.cpp b/src/graphics/PostProcessing.cpp new file mode 100644 index 00000000..3c33fad4 --- /dev/null +++ b/src/graphics/PostProcessing.cpp @@ -0,0 +1,42 @@ +#include "PostProcessing.h" +#include "Mesh.h" +#include "Shader.h" +#include "Texture.h" +#include "Framebuffer.h" + +#include + +PostProcessing::PostProcessing() { + // Fullscreen quad mesh bulding + float vertices[] { + -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f + }; + vattr attrs[] {{2}, {0}}; + quadMesh = std::make_unique(vertices, 6, attrs); +} + +PostProcessing::~PostProcessing() { +} + +void PostProcessing::use(GfxContext& context) { + const auto& vp = context.getViewport(); + if (fbo) { + fbo->resize(vp.getWidth(), vp.getHeight()); + } else { + fbo = std::make_unique(vp.getWidth(), vp.getHeight()); + } + context.setFramebuffer(fbo.get()); +} + +void PostProcessing::render(GfxContext& context, Shader* screenShader) { + if (fbo == nullptr) { + throw std::runtime_error("'use(...)' was never called"); + } + + const auto& viewport = context.getViewport(); + screenShader->use(); + screenShader->uniform2i("u_screenSize", viewport.size()); + fbo->getTexture()->bind(); + quadMesh->draw(); +} diff --git a/src/graphics/PostProcessing.h b/src/graphics/PostProcessing.h new file mode 100644 index 00000000..efd1e36a --- /dev/null +++ b/src/graphics/PostProcessing.h @@ -0,0 +1,37 @@ +#ifndef GRAPHICS_POST_PROCESSING_H_ +#define GRAPHICS_POST_PROCESSING_H_ + +#include "Viewport.h" +#include "GfxContext.h" + +#include + +class Mesh; +class Shader; +class Framebuffer; + +/// @brief Framebuffer with blitting with shaders. +/// @attention Current implementation does not support multiple render passes +/// for multiple effects. Will be implemented in v0.21 +class PostProcessing { + /// @brief Main framebuffer (lasy field) + std::unique_ptr fbo; + /// @brief Fullscreen quad mesh as the post-processing canvas + std::unique_ptr quadMesh; +public: + PostProcessing(); + ~PostProcessing(); + + /// @brief Prepare and bind framebuffer + /// @param context graphics context will be modified + void use(GfxContext& context); + + /// @brief Render fullscreen quad using the passed shader + /// with framebuffer texture bound + /// @param context graphics context + /// @param screenShader shader used for fullscreen quad + /// @throws std::runtime_error if use(...) wasn't called before + void render(GfxContext& context, Shader* screenShader); +}; + +#endif // GRAPHICS_POST_PROCESSING_H_ diff --git a/src/graphics/Shader.cpp b/src/graphics/Shader.cpp index 7d620906..ff68ddad 100644 --- a/src/graphics/Shader.cpp +++ b/src/graphics/Shader.cpp @@ -52,6 +52,11 @@ void Shader::uniform2f(std::string name, glm::vec2 xy){ glUniform2f(transformLoc, xy.x, xy.y); } +void Shader::uniform2i(std::string name, glm::ivec2 xy){ + GLuint transformLoc = glGetUniformLocation(id, name.c_str()); + glUniform2i(transformLoc, xy.x, xy.y); +} + void Shader::uniform3f(std::string name, float x, float y, float z){ GLuint transformLoc = glGetUniformLocation(id, name.c_str()); glUniform3f(transformLoc, x,y,z); diff --git a/src/graphics/Shader.h b/src/graphics/Shader.h index 851a2806..e2052937 100644 --- a/src/graphics/Shader.h +++ b/src/graphics/Shader.h @@ -21,6 +21,7 @@ public: void uniform1f(std::string name, float x); void uniform2f(std::string name, float x, float y); void uniform2f(std::string name, glm::vec2 xy); + void uniform2i(std::string name, glm::ivec2 xy); void uniform3f(std::string name, float x, float y, float z); void uniform3f(std::string name, glm::vec3 xyz); diff --git a/src/graphics/Viewport.h b/src/graphics/Viewport.h index da027b8e..3bfee7ca 100644 --- a/src/graphics/Viewport.h +++ b/src/graphics/Viewport.h @@ -14,8 +14,8 @@ public: virtual uint getWidth() const; virtual uint getHeight() const; - glm::vec2 size() const { - return glm::vec2(width, height); + glm::ivec2 size() const { + return glm::ivec2(width, height); } }; From a570e12a04bfda9aa126420f4f1cc70c215e6cfa Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 8 Mar 2024 21:50:24 +0300 Subject: [PATCH 07/11] warnings fix --- src/logic/scripting/scripting.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logic/scripting/scripting.h b/src/logic/scripting/scripting.h index 5dbc8878..12b3dea8 100644 --- a/src/logic/scripting/scripting.h +++ b/src/logic/scripting/scripting.h @@ -45,7 +45,7 @@ namespace scripting { extern bool register_event(int env, const std::string& name, const std::string& id); - static int noargs(lua::LuaState *) { return 0; } + static inline int noargs(lua::LuaState *) { return 0; } extern bool emit_event(const std::string& name, std::function args = noargs); std::unique_ptr create_environment(int parent=0); From 8ea3db99629fec7be6bcc8967dbd54a6ebfd1945 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 8 Mar 2024 21:54:17 +0300 Subject: [PATCH 08/11] screen shader replaced with default --- res/shaders/screen.glslf | 6 +----- res/shaders/screen.glslv | 1 + src/graphics/Framebuffer.cpp | 1 - 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/res/shaders/screen.glslf b/res/shaders/screen.glslf index a3bb7ff9..0117b59f 100644 --- a/res/shaders/screen.glslf +++ b/res/shaders/screen.glslf @@ -2,12 +2,8 @@ in vec2 v_coord; out vec4 f_color; uniform sampler2D u_texture0; -uniform float u_timer; void main(){ - vec2 coord = v_coord; - coord.x += sin(u_timer*5.0+coord.x*4.0) * 0.02; - coord.y += cos(u_timer*5.0+coord.y*4.0) * 0.02; - f_color = texture(u_texture0, coord); + f_color = texture(u_texture0, v_coord); } diff --git a/res/shaders/screen.glslv b/res/shaders/screen.glslv index 772e5f06..b319c53f 100644 --- a/res/shaders/screen.glslv +++ b/res/shaders/screen.glslv @@ -4,6 +4,7 @@ out vec2 v_coord; uniform ivec2 u_screenSize; uniform float u_timer; +uniform float u_dayTime; void main(){ v_coord = v_position * 0.5 + 0.5; diff --git a/src/graphics/Framebuffer.cpp b/src/graphics/Framebuffer.cpp index 7e19c4f5..5224bb2e 100644 --- a/src/graphics/Framebuffer.cpp +++ b/src/graphics/Framebuffer.cpp @@ -59,7 +59,6 @@ void Framebuffer::resize(uint width, uint height) { if (this->width == width && this->height == height) { return; } - GLuint texid = texture->getId(); texture->bind(); glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, nullptr); texture->unbind(); From 07dc12143effd61f6b3605ef202b9f64d54d3875 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 8 Mar 2024 22:21:18 +0300 Subject: [PATCH 09/11] WorldRenderer refactor --- src/frontend/WorldRenderer.cpp | 249 +++++++++++++++++--------------- src/frontend/WorldRenderer.h | 28 +++- src/graphics/PostProcessing.cpp | 2 +- src/graphics/PostProcessing.h | 2 +- 4 files changed, 163 insertions(+), 118 deletions(-) diff --git a/src/frontend/WorldRenderer.cpp b/src/frontend/WorldRenderer.cpp index 69888891..4458b1f2 100644 --- a/src/frontend/WorldRenderer.cpp +++ b/src/frontend/WorldRenderer.cpp @@ -138,21 +138,137 @@ void WorldRenderer::drawChunks(Chunks* chunks, Camera* camera, Shader* shader) { } } +void WorldRenderer::renderLevel( + const GfxContext& ctx, + Camera* camera, + const EngineSettings& settings +) { + Assets* assets = engine->getAssets(); + Atlas* atlas = assets->getAtlas("blocks"); + Shader* shader = assets->getShader("main"); + auto indices = level->content->getIndices(); + + float fogFactor = 15.0f / ((float)settings.chunks.loadDistance-2); + + // Setting up main shader + shader->use(); + shader->uniformMatrix("u_proj", camera->getProjection()); + shader->uniformMatrix("u_view", camera->getView()); + shader->uniform1f("u_gamma", settings.graphics.gamma); + shader->uniform1f("u_fogFactor", fogFactor); + shader->uniform1f("u_fogCurve", settings.graphics.fogCurve); + shader->uniform1f("u_dayTime", level->world->daytime); + shader->uniform3f("u_cameraPos", camera->position); + shader->uniform1i("u_cubemap", 1); + + // Light emission when an emissive item is chosen + { + auto inventory = player->getInventory(); + ItemStack& stack = inventory->getSlot(player->getChosenSlot()); + auto item = indices->getItemDef(stack.getItemId()); + float multiplier = 0.5f; + shader->uniform3f("u_torchlightColor", + item->emission[0] / 15.0f * multiplier, + item->emission[1] / 15.0f * multiplier, + item->emission[2] / 15.0f * multiplier + ); + shader->uniform1f("u_torchlightDistance", 6.0f); + } + + // Binding main shader textures + skybox->bind(); + atlas->getTexture()->bind(); + + drawChunks(level->chunks.get(), camera, shader); + + skybox->unbind(); +} + +void WorldRenderer::renderBlockSelection(Camera* camera, Shader* linesShader) { + auto indices = level->content->getIndices(); + blockid_t id = PlayerController::selectedBlockId; + auto block = indices->getBlockDef(id); + const glm::vec3 pos = PlayerController::selectedBlockPosition; + const glm::vec3 point = PlayerController::selectedPointPosition; + const glm::vec3 norm = PlayerController::selectedBlockNormal; + + std::vector& hitboxes = block->rotatable + ? block->rt.hitboxes[PlayerController::selectedBlockStates] + : block->hitboxes; + + linesShader->use(); + linesShader->uniformMatrix("u_projview", camera->getProjView()); + lineBatch->lineWidth(2.0f); + for (auto& hitbox: hitboxes) { + const glm::vec3 center = pos + hitbox.center(); + const glm::vec3 size = hitbox.size(); + lineBatch->box(center, size + glm::vec3(0.02), glm::vec4(0.f, 0.f, 0.f, 0.5f)); + if (player->debug) { + lineBatch->line(point, point+norm*0.5f, glm::vec4(1.0f, 0.0f, 1.0f, 1.0f)); + } + } + lineBatch->render(); +} + +void WorldRenderer::renderDebugLines( + const GfxContext& pctx, + Camera* camera, + Shader* linesShader, + const EngineSettings& settings +) { + GfxContext ctx = pctx.sub(); + const auto& viewport = ctx.getViewport(); + uint displayWidth = viewport.getWidth(); + uint displayHeight = viewport.getHeight(); + + ctx.setDepthTest(true); + + linesShader->use(); + + if (settings.debug.showChunkBorders){ + linesShader->uniformMatrix("u_projview", camera->getProjView()); + glm::vec3 coord = player->camera->position; + if (coord.x < 0) coord.x--; + if (coord.z < 0) coord.z--; + int cx = floordiv((int)coord.x, CHUNK_W); + int cz = floordiv((int)coord.z, CHUNK_D); + + drawBorders( + cx * CHUNK_W, 0, cz * CHUNK_D, + (cx + 1) * CHUNK_W, CHUNK_H, (cz + 1) * CHUNK_D + ); + } + + float length = 40.f; + glm::vec3 tsl(displayWidth/2, displayHeight/2, 0.f); + glm::mat4 model(glm::translate(glm::mat4(1.f), tsl)); + linesShader->uniformMatrix("u_projview", glm::ortho( + 0.f, (float)displayWidth, + 0.f, (float)displayHeight, + -length, length) * model * glm::inverse(camera->rotation) + ); + + ctx.setDepthTest(false); + lineBatch->lineWidth(4.0f); + lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); + lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 1.f); + lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 1.f); + lineBatch->render(); + + ctx.setDepthTest(true); + lineBatch->lineWidth(2.0f); + lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f); + lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 1.f); + lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 1.f); + lineBatch->render(); +} void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible){ EngineSettings& settings = engine->getSettings(); skybox->refresh(pctx, level->world->daytime, 1.0f+fog*2.0f, 4); - const Content* content = level->content; - auto indices = content->getIndices(); Assets* assets = engine->getAssets(); - Atlas* atlas = assets->getAtlas("blocks"); - Shader* shader = assets->getShader("main"); Shader* linesShader = assets->getShader("lines"); - - const Viewport& viewport = pctx.getViewport(); - int displayWidth = viewport.getWidth(); - int displayHeight = viewport.getHeight(); // World render scope with diegetic HUD included { @@ -168,122 +284,25 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible { GfxContext ctx = wctx.sub(); ctx.setDepthTest(true); - ctx.setCullFace(true); - - float fogFactor = 15.0f / ((float)settings.chunks.loadDistance-2); - - // Setting up main shader - shader->use(); - shader->uniformMatrix("u_proj", camera->getProjection()); - shader->uniformMatrix("u_view", camera->getView()); - shader->uniform1f("u_gamma", settings.graphics.gamma); - shader->uniform1f("u_fogFactor", fogFactor); - shader->uniform1f("u_fogCurve", settings.graphics.fogCurve); - shader->uniform1f("u_dayTime", level->world->daytime); - shader->uniform3f("u_cameraPos", camera->position); - shader->uniform1i("u_cubemap", 1); - - // Light emission when an emissive item is chosen - { - auto inventory = player->getInventory(); - ItemStack& stack = inventory->getSlot(player->getChosenSlot()); - auto item = indices->getItemDef(stack.getItemId()); - float multiplier = 0.5f; - shader->uniform3f("u_torchlightColor", - item->emission[0] / 15.0f * multiplier, - item->emission[1] / 15.0f * multiplier, - item->emission[2] / 15.0f * multiplier - ); - shader->uniform1f("u_torchlightDistance", 6.0f); - } - - // Binding main shader textures - skybox->bind(); - atlas->getTexture()->bind(); - - drawChunks(level->chunks.get(), camera, shader); - + ctx.setCullFace(true); + renderLevel(ctx, camera, settings); // Selected block if (PlayerController::selectedBlockId != -1 && hudVisible){ - blockid_t id = PlayerController::selectedBlockId; - auto block = indices->getBlockDef(id); - const glm::vec3 pos = PlayerController::selectedBlockPosition; - const glm::vec3 point = PlayerController::selectedPointPosition; - const glm::vec3 norm = PlayerController::selectedBlockNormal; - - std::vector& hitboxes = block->rotatable - ? block->rt.hitboxes[PlayerController::selectedBlockStates] - : block->hitboxes; - - linesShader->use(); - linesShader->uniformMatrix("u_projview", camera->getProjView()); - lineBatch->lineWidth(2.0f); - for (auto& hitbox: hitboxes) { - const glm::vec3 center = pos + hitbox.center(); - const glm::vec3 size = hitbox.size(); - lineBatch->box(center, size + glm::vec3(0.02), glm::vec4(0.f, 0.f, 0.f, 0.5f)); - if (player->debug) { - lineBatch->line(point, point+norm*0.5f, glm::vec4(1.0f, 0.0f, 1.0f, 1.0f)); - } - } - lineBatch->render(); + renderBlockSelection(camera, linesShader); } - skybox->unbind(); } if (hudVisible && player->debug) { - GfxContext ctx = pctx.sub(); - ctx.setDepthTest(true); - - linesShader->use(); - - if (settings.debug.showChunkBorders){ - linesShader->uniformMatrix("u_projview", camera->getProjView()); - glm::vec3 coord = player->camera->position; - if (coord.x < 0) coord.x--; - if (coord.z < 0) coord.z--; - int cx = floordiv((int)coord.x, CHUNK_W); - int cz = floordiv((int)coord.z, CHUNK_D); - - drawBorders(cx * CHUNK_W, 0, cz * CHUNK_D, - (cx + 1) * CHUNK_W, CHUNK_H, (cz + 1) * CHUNK_D); - } - - float length = 40.f; - glm::vec3 tsl(displayWidth/2, displayHeight/2, 0.f); - glm::mat4 model(glm::translate(glm::mat4(1.f), tsl)); - linesShader->uniformMatrix("u_projview", glm::ortho( - 0.f, (float)displayWidth, - 0.f, (float)displayHeight, - -length, length) * model * glm::inverse(camera->rotation)); - - ctx.setDepthTest(false); - lineBatch->lineWidth(4.0f); - lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); - lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 1.f); - lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 1.f); - lineBatch->render(); - - ctx.setDepthTest(true); - lineBatch->lineWidth(2.0f); - lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f); - lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 1.f); - lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 1.f); - lineBatch->render(); + renderDebugLines(wctx, camera, linesShader, settings); } } - { - GfxContext ctx = pctx.sub(); - ctx.setDepthTest(false); - - auto shader = assets->getShader("screen"); - shader->use(); - shader->uniform1f("u_timer", Window::time()); - shader->uniform1f("u_dayTime", level->world->daytime); - - postProcessing->render(ctx, shader); - } + // Rendering fullscreen quad with + auto screenShader = assets->getShader("screen"); + screenShader->use(); + screenShader->uniform1f("u_timer", Window::time()); + screenShader->uniform1f("u_dayTime", level->world->daytime); + postProcessing->render(pctx, screenShader); } void WorldRenderer::drawBorders(int sx, int sy, int sz, int ex, int ey, int ez) { diff --git a/src/frontend/WorldRenderer.h b/src/frontend/WorldRenderer.h index 7c56c3e7..9129c83d 100644 --- a/src/frontend/WorldRenderer.h +++ b/src/frontend/WorldRenderer.h @@ -39,12 +39,38 @@ class WorldRenderer { std::unique_ptr batch3d; bool drawChunk(size_t index, Camera* camera, Shader* shader, bool culling); void drawChunks(Chunks* chunks, Camera* camera, Shader* shader); + + /// @brief Render level without diegetic interface + /// @param context graphics context + /// @param camera active camera + /// @param settings engine settings + void renderLevel( + const GfxContext& context, + Camera* camera, + const EngineSettings& settings + ); + + /// @brief Render block selection lines + /// @param camera active camera + /// @param linesShader shader used + void renderBlockSelection(Camera* camera, Shader* linesShader); + + /// @brief Render all debug lines (chunks borders, coord system guides) + /// @param context graphics context + /// @param camera active camera + /// @param linesShader shader used + /// @param settings engine settings + void renderDebugLines( + const GfxContext& context, + Camera* camera, + Shader* linesShader, + const EngineSettings& settings + ); public: WorldRenderer(Engine* engine, LevelFrontend* frontend, Player* player); ~WorldRenderer(); void draw(const GfxContext& context, Camera* camera, bool hudVisible); - void drawDebug(const GfxContext& context, Camera* camera); void drawBorders(int sx, int sy, int sz, int ex, int ey, int ez); static float fog; diff --git a/src/graphics/PostProcessing.cpp b/src/graphics/PostProcessing.cpp index 3c33fad4..4fa3b4fd 100644 --- a/src/graphics/PostProcessing.cpp +++ b/src/graphics/PostProcessing.cpp @@ -29,7 +29,7 @@ void PostProcessing::use(GfxContext& context) { context.setFramebuffer(fbo.get()); } -void PostProcessing::render(GfxContext& context, Shader* screenShader) { +void PostProcessing::render(const GfxContext& context, Shader* screenShader) { if (fbo == nullptr) { throw std::runtime_error("'use(...)' was never called"); } diff --git a/src/graphics/PostProcessing.h b/src/graphics/PostProcessing.h index efd1e36a..d49894e3 100644 --- a/src/graphics/PostProcessing.h +++ b/src/graphics/PostProcessing.h @@ -31,7 +31,7 @@ public: /// @param context graphics context /// @param screenShader shader used for fullscreen quad /// @throws std::runtime_error if use(...) wasn't called before - void render(GfxContext& context, Shader* screenShader); + void render(const GfxContext& context, Shader* screenShader); }; #endif // GRAPHICS_POST_PROCESSING_H_ From 93979b2e5358be682385e58df472a2a63ab17386 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 8 Mar 2024 22:31:32 +0300 Subject: [PATCH 10/11] LMPacker indents fix --- src/maths/LMPacker.cpp | 188 ++++++++++++++++++++--------------------- src/maths/LMPacker.h | 60 ++++++------- 2 files changed, 124 insertions(+), 124 deletions(-) diff --git a/src/maths/LMPacker.cpp b/src/maths/LMPacker.cpp index 298c1586..c23ac2f6 100644 --- a/src/maths/LMPacker.cpp +++ b/src/maths/LMPacker.cpp @@ -3,83 +3,83 @@ #include inline int getPackerScore(rectangle& rect) { - if (rect.width * rect.height > 100) - return rect.height * rect.height * 1000; - return (rect.width * rect.height * rect.height); + if (rect.width * rect.height > 100) + return rect.height * rect.height * 1000; + return (rect.width * rect.height * rect.height); } LMPacker::LMPacker(const uint32_t sizes[], size_t length) { - for (unsigned int i = 0; i < length/2; i++) { - rectangle rect(i, 0, 0, (int)sizes[i * 2], (int)sizes[i * 2 + 1]); - rects.push_back(rect); - } - sort(rects.begin(), rects.end(), [](rectangle a, rectangle b) { - return -getPackerScore(a) < -getPackerScore(b); - }); + for (unsigned int i = 0; i < length/2; i++) { + rectangle rect(i, 0, 0, (int)sizes[i * 2], (int)sizes[i * 2 + 1]); + rects.push_back(rect); + } + sort(rects.begin(), rects.end(), [](rectangle a, rectangle b) { + return -getPackerScore(a) < -getPackerScore(b); + }); } LMPacker::~LMPacker() { - if (matrix) { - for (unsigned int y = 0; y < (height >> mbit); y++) { - delete[] matrix[y]; - } - delete[] matrix; - } + if (matrix) { + for (unsigned int y = 0; y < (height >> mbit); y++) { + delete[] matrix[y]; + } + delete[] matrix; + } } void LMPacker::cleanup() { - placed.clear(); + placed.clear(); } bool LMPacker::build(uint32_t width, uint32_t height, uint16_t extension, uint32_t mbit, uint32_t vstep) { - cleanup(); - this->mbit = mbit; - this->width = width; - this->height = height; - int mpix = 1 << mbit; + cleanup(); + this->mbit = mbit; + this->width = width; + this->height = height; + int mpix = 1 << mbit; - const unsigned int mwidth = width >> mbit; - const unsigned int mheight = height >> mbit; - matrix = new rectangle**[mheight]; - for (unsigned int y = 0; y < mheight; y++) { - matrix[y] = new rectangle*[mwidth]; - for (unsigned int x = 0; x < mwidth; x++) { - matrix[y][x] = nullptr; - } - } - for (unsigned int i = 0; i < rects.size(); i++) { - rectangle& rect = rects[i]; - rect = rectangle(rect.idx, 0, 0, rect.width, rect.height); + const unsigned int mwidth = width >> mbit; + const unsigned int mheight = height >> mbit; + matrix = new rectangle**[mheight]; + for (unsigned int y = 0; y < mheight; y++) { + matrix[y] = new rectangle*[mwidth]; + for (unsigned int x = 0; x < mwidth; x++) { + matrix[y][x] = nullptr; + } + } + for (unsigned int i = 0; i < rects.size(); i++) { + rectangle& rect = rects[i]; + rect = rectangle(rect.idx, 0, 0, rect.width, rect.height); rect.width += extension * 2; rect.height += extension * 2; if (mpix > 1) { - if (rect.width % mpix > 0) { - rect.extX = mpix - (rect.width % mpix); - } - if (rect.height % mpix > 0) { - rect.extY = mpix - (rect.height % mpix); - } - } - rect.width += rect.extX; - rect.height += rect.extY; - } - bool built = true; - for (unsigned int i = 0; i < rects.size(); i++) { - rectangle* rect = &rects[i]; - if (!place(rect, vstep)) { - built = false; - break; - } - } - for (unsigned int i = 0; i < rects.size(); i++) { - rectangle& rect = rects[i]; + if (rect.width % mpix > 0) { + rect.extX = mpix - (rect.width % mpix); + } + if (rect.height % mpix > 0) { + rect.extY = mpix - (rect.height % mpix); + } + } + rect.width += rect.extX; + rect.height += rect.extY; + } + bool built = true; + for (unsigned int i = 0; i < rects.size(); i++) { + rectangle* rect = &rects[i]; + if (!place(rect, vstep)) { + built = false; + break; + } + } + for (unsigned int i = 0; i < rects.size(); i++) { + rectangle& rect = rects[i]; rect.x += extension; rect.y += extension; rect.width -= extension * 2 + rect.extX; rect.height -= extension * 2 + rect.extY; - } - return built; + } + return built; } inline rectangle* findCollision(rectangle*** matrix, int x, int y, int w, int h) { @@ -103,47 +103,47 @@ inline void fill(rectangle*** matrix, rectangle* rect, int x, int y, int w, int } bool LMPacker::place(rectangle* rectptr, uint32_t vstep) { - rectangle& rect = *rectptr; - const unsigned int rw = rect.width >> mbit; - const unsigned int rh = rect.height >> mbit; - if (vstep > 1) { - vstep = (vstep > rh ? vstep : rh); - } - const unsigned int mwidth = width >> mbit; - const unsigned int mheight = height >> mbit; - for (unsigned int y = 0; y + rh < mheight; y += vstep) { - rectangle** line = matrix[y]; - bool skiplines = true; - rectangle** lower = matrix[y + rh - 1]; - for (unsigned int x = 0; x + rw < mwidth; x++) { - rectangle* prect = line[x]; - if (prect) { - x = (prect->x >> mbit) + (prect->width >> mbit) - 1; - } else { - if (skiplines) { - unsigned int lfree = 0; - while (lfree + x < mwidth && !lower[x + lfree] && lfree < rw) { - lfree++; - } - if (lfree >= rw) - skiplines = false; - } - prect = findCollision(matrix, x, y, rw, rh); - if (prect) { - x = (prect->x >> mbit) + (prect->width >> mbit) - 1; - continue; - } - fill(matrix, rectptr, x, y, rw, rh); + rectangle& rect = *rectptr; + const unsigned int rw = rect.width >> mbit; + const unsigned int rh = rect.height >> mbit; + if (vstep > 1) { + vstep = (vstep > rh ? vstep : rh); + } + const unsigned int mwidth = width >> mbit; + const unsigned int mheight = height >> mbit; + for (unsigned int y = 0; y + rh < mheight; y += vstep) { + rectangle** line = matrix[y]; + bool skiplines = true; + rectangle** lower = matrix[y + rh - 1]; + for (unsigned int x = 0; x + rw < mwidth; x++) { + rectangle* prect = line[x]; + if (prect) { + x = (prect->x >> mbit) + (prect->width >> mbit) - 1; + } else { + if (skiplines) { + unsigned int lfree = 0; + while (lfree + x < mwidth && !lower[x + lfree] && lfree < rw) { + lfree++; + } + if (lfree >= rw) + skiplines = false; + } + prect = findCollision(matrix, x, y, rw, rh); + if (prect) { + x = (prect->x >> mbit) + (prect->width >> mbit) - 1; + continue; + } + fill(matrix, rectptr, x, y, rw, rh); rectptr->x = x << mbit; rectptr->y = y << mbit; placed.push_back(rectptr); return true; - } - } - if (skiplines) { - y += rh - vstep; - } - } - return false; + } + } + if (skiplines) { + y += rh - vstep; + } + } + return false; } diff --git a/src/maths/LMPacker.h b/src/maths/LMPacker.h index 78f6c1c5..9c49b07f 100644 --- a/src/maths/LMPacker.h +++ b/src/maths/LMPacker.h @@ -10,44 +10,44 @@ #include struct rectangle { - unsigned int idx; - int x; - int y; - int width; - int height; - int extX = 0; - int extY = 0; + unsigned int idx; + int x; + int y; + int width; + int height; + int extX = 0; + int extY = 0; - rectangle(unsigned int idx, int x, int y, int width, int height) - : idx(idx), x(x), y(y), width(width), height(height){ - } + rectangle(unsigned int idx, int x, int y, int width, int height) + : idx(idx), x(x), y(y), width(width), height(height){ + } }; class LMPacker { - std::vector rects; - std::vector placed; - uint32_t width = 0; - uint32_t height = 0; - rectangle*** matrix = nullptr; - uint32_t mbit = 0; + std::vector rects; + std::vector placed; + uint32_t width = 0; + uint32_t height = 0; + rectangle*** matrix = nullptr; + uint32_t mbit = 0; - void cleanup(); - bool place(rectangle* rect, uint32_t vstep); + void cleanup(); + bool place(rectangle* rect, uint32_t vstep); public: - LMPacker(const uint32_t sizes[], size_t length); - virtual ~LMPacker(); + LMPacker(const uint32_t sizes[], size_t length); + virtual ~LMPacker(); - bool buildCompact(uint32_t width, uint32_t height, uint16_t extension) { - return build(width, height, extension, 0, 1); - } - bool buildFast(uint32_t width, uint32_t height, uint16_t extension) { - return build(width, height, extension, 1, 2); - } - bool build(uint32_t width, uint32_t height, uint16_t extension, uint32_t mbit, uint32_t vstep); + bool buildCompact(uint32_t width, uint32_t height, uint16_t extension) { + return build(width, height, extension, 0, 1); + } + bool buildFast(uint32_t width, uint32_t height, uint16_t extension) { + return build(width, height, extension, 1, 2); + } + bool build(uint32_t width, uint32_t height, uint16_t extension, uint32_t mbit, uint32_t vstep); - std::vector getResult() { - return rects; - } + std::vector getResult() { + return rects; + } }; #endif /* LMPACKER_H_ */ \ No newline at end of file From ff7e39ed272aac89c3e455d635fe9e09cd8a1f09 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 8 Mar 2024 22:48:06 +0300 Subject: [PATCH 11/11] fix --- src/maths/LMPacker.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/maths/LMPacker.cpp b/src/maths/LMPacker.cpp index c23ac2f6..804bd0be 100644 --- a/src/maths/LMPacker.cpp +++ b/src/maths/LMPacker.cpp @@ -19,15 +19,16 @@ LMPacker::LMPacker(const uint32_t sizes[], size_t length) { } LMPacker::~LMPacker() { + cleanup(); +} + +void LMPacker::cleanup() { if (matrix) { for (unsigned int y = 0; y < (height >> mbit); y++) { delete[] matrix[y]; } delete[] matrix; } -} - -void LMPacker::cleanup() { placed.clear(); } @@ -41,6 +42,7 @@ bool LMPacker::build(uint32_t width, uint32_t height, const unsigned int mwidth = width >> mbit; const unsigned int mheight = height >> mbit; + matrix = new rectangle**[mheight]; for (unsigned int y = 0; y < mheight; y++) { matrix[y] = new rectangle*[mwidth]; @@ -48,6 +50,7 @@ bool LMPacker::build(uint32_t width, uint32_t height, matrix[y][x] = nullptr; } } + for (unsigned int i = 0; i < rects.size(); i++) { rectangle& rect = rects[i]; rect = rectangle(rect.idx, 0, 0, rect.width, rect.height);