From 45d79e99e8e68c5bdb7f18baf4ac48eb229a93df Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Fri, 29 Oct 2021 00:57:59 -0500 Subject: [PATCH] [nostalgia] Move much of the OpenGL code to glutils --- src/nostalgia/core/CMakeLists.txt | 1 + src/nostalgia/core/media.hpp | 9 +++ src/nostalgia/core/userland/gfx.cpp | 8 +- src/nostalgia/core/userland/gfx_opengl.cpp | 86 ++++++++-------------- src/nostalgia/glutils/glutils.cpp | 33 ++++++++- src/nostalgia/glutils/glutils.hpp | 28 ++++++- 6 files changed, 99 insertions(+), 66 deletions(-) diff --git a/src/nostalgia/core/CMakeLists.txt b/src/nostalgia/core/CMakeLists.txt index 4958fc80..92bfc075 100644 --- a/src/nostalgia/core/CMakeLists.txt +++ b/src/nostalgia/core/CMakeLists.txt @@ -10,6 +10,7 @@ endif() target_link_libraries( NostalgiaCore PUBLIC + OxClaw OxFS ) diff --git a/src/nostalgia/core/media.hpp b/src/nostalgia/core/media.hpp index 904e245b..b4875573 100644 --- a/src/nostalgia/core/media.hpp +++ b/src/nostalgia/core/media.hpp @@ -8,10 +8,19 @@ #pragma once +#include #include +#include "context.hpp" + namespace nostalgia::core { +template +ox::Result readObj(Context *ctx, const ox::FileAddress &file) noexcept { + oxRequire(buff, ctx->rom->read(file)); + return ox::readClaw(buff); +} + ox::Result> loadRomFs(const char *path) noexcept; ox::Result loadRom(const char *path = "") noexcept; diff --git a/src/nostalgia/core/userland/gfx.cpp b/src/nostalgia/core/userland/gfx.cpp index 240ba3e5..979a0c47 100644 --- a/src/nostalgia/core/userland/gfx.cpp +++ b/src/nostalgia/core/userland/gfx.cpp @@ -6,19 +6,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include #include +#include #include "gfx.hpp" namespace nostalgia::core { -template -static ox::Result readObj(Context *ctx, const ox::FileAddress &file) noexcept { - oxRequire(buff, ctx->rom->read(file)); - return ox::readClaw(buff); -} - ox::Error initConsole(Context *ctx) noexcept { constexpr auto TilesheetAddr = "/TileSheets/Charset.ng"; constexpr auto PaletteAddr = "/Palettes/Charset.npal"; diff --git a/src/nostalgia/core/userland/gfx_opengl.cpp b/src/nostalgia/core/userland/gfx_opengl.cpp index 10ed56e1..a45821bd 100644 --- a/src/nostalgia/core/userland/gfx_opengl.cpp +++ b/src/nostalgia/core/userland/gfx_opengl.cpp @@ -33,15 +33,14 @@ constexpr auto BgVertexVboRowLength = 4; constexpr auto BgVertexVboLength = BgVertexVboRows * BgVertexVboRowLength; constexpr auto BgVertexEboLength = 6; -struct Background { - glutils::GLVertexArray vao; - glutils::GLBuffer vbo; - glutils::GLBuffer ebo; - glutils::GLTexture tex; +struct Background: public glutils::BufferSet { bool enabled = false; bool updated = false; - std::array bgVertices = {}; - std::array bgElements = {}; + + inline Background() noexcept { + vertices.resize(TileCount * BgVertexVboLength); + elements.resize(TileCount * BgVertexEboLength); + } }; struct GlImplData { @@ -54,11 +53,11 @@ struct GlImplData { constexpr const GLchar *bgvshad = R"( {} in vec2 vTexCoord; - in vec2 position; + in vec2 vPosition; out vec2 fTexCoord; uniform float vTileHeight; void main() { - gl_Position = vec4(position, 0.0, 1.0); + gl_Position = vec4(vPosition, 0.0, 1.0); fTexCoord = vTexCoord * vec2(1, vTileHeight); })"; @@ -77,7 +76,8 @@ static constexpr auto bgVertexRow(unsigned x, unsigned y) noexcept { return y * TileRows + x; } -static void setTileBufferObject(Context *ctx, unsigned vi, float x, float y, int textureRow, float *vbo, GLuint *ebo) { +static void +setTileBufferObject(Context *ctx, unsigned vi, float x, float y, int textureRow, float *vbo, GLuint *ebo) noexcept { // don't worry, this memcpy gets optimized to something much more ideal const auto [sw, sh] = getScreenSize(ctx); constexpr float ymod = 2.0f / 20.0f; @@ -100,59 +100,35 @@ static void setTileBufferObject(Context *ctx, unsigned vi, float x, float y, int memcpy(ebo, elms, sizeof(elms)); } -static void sendVbo(const Background &bg) noexcept { - // vbo - glBindBuffer(GL_ARRAY_BUFFER, bg.vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(bg.bgVertices), &bg.bgVertices, GL_DYNAMIC_DRAW); -} - -static void sendEbo(const Background &bg) noexcept { - // ebo - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bg.ebo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(bg.bgElements), &bg.bgElements, GL_STATIC_DRAW); -} - -static void initBackgroundBufferObjects(Context *ctx, Background *bg) noexcept { +static void initBackgroundBufferObjects(Context *ctx, glutils::BufferSet *bg) noexcept { for (auto x = 0u; x < TileColumns; ++x) { for (auto y = 0u; y < TileRows; ++y) { const auto i = bgVertexRow(x, y); - auto vbo = &bg->bgVertices[i * BgVertexVboLength]; - auto ebo = &bg->bgElements[i * BgVertexEboLength]; + auto vbo = &bg->vertices[i * BgVertexVboLength]; + auto ebo = &bg->elements[i * BgVertexEboLength]; setTileBufferObject(ctx, i * BgVertexVboRows, static_cast(x), static_cast(y), 0, vbo, ebo); } } } -static glutils::GLVertexArray genVertexArrayObject() noexcept { - GLuint vao = 0; - glGenVertexArrays(1, &vao); - return glutils::GLVertexArray(vao); -} - -static glutils::GLBuffer genBuffer() noexcept { - GLuint buff = 0; - glGenBuffers(1, &buff); - return glutils::GLBuffer(buff); -} - -static void initBackgroundBufferset(Context *ctx, GLuint shader, Background *bg) noexcept { +static void initBackgroundBufferset(Context *ctx, GLuint shader, glutils::BufferSet *bg) noexcept { // vao - bg->vao = genVertexArrayObject(); + bg->vao = glutils::generateVertexArrayObject(); glBindVertexArray(bg->vao); // vbo & ebo - bg->vbo = genBuffer(); - bg->ebo = genBuffer(); + bg->vbo = glutils::generateBuffer(); + bg->ebo = glutils::generateBuffer(); initBackgroundBufferObjects(ctx, bg); - sendVbo(*bg); - sendEbo(*bg); + glutils::sendVbo(*bg); + glutils::sendEbo(*bg); // vbo layout - auto posAttr = static_cast(glGetAttribLocation(shader, "position")); + auto posAttr = static_cast(glGetAttribLocation(shader, "vPosition")); glEnableVertexAttribArray(posAttr); glVertexAttribPointer(posAttr, 2, GL_FLOAT, GL_FALSE, BgVertexVboRowLength * sizeof(float), nullptr); auto texCoordAttr = static_cast(glGetAttribLocation(shader, "vTexCoord")); glEnableVertexAttribArray(texCoordAttr); glVertexAttribPointer(texCoordAttr, 2, GL_FLOAT, GL_FALSE, BgVertexVboRowLength * sizeof(float), - ox::bit_cast(2 * sizeof(float))); + std::bit_cast(2 * sizeof(float))); } static glutils::GLTexture loadTexture(GLsizei w, GLsizei h, void *pixels) noexcept { @@ -192,10 +168,10 @@ static void drawBackground(Background *bg) noexcept { glBindVertexArray(bg->vao); if (bg->updated) { bg->updated = false; - renderer::sendVbo(*bg); + glutils::sendVbo(*bg); } glBindTexture(GL_TEXTURE_2D, bg->tex); - glDrawElements(GL_TRIANGLES, static_cast(bg->bgElements.size()), GL_UNSIGNED_INT, nullptr); + glDrawElements(GL_TRIANGLES, static_cast(bg->elements.size()), GL_UNSIGNED_INT, nullptr); } } @@ -210,16 +186,15 @@ static void drawBackgrounds(GlImplData *id) noexcept { } ox::Error init(Context *ctx) noexcept { - constexpr auto GlslVersion = "#version 150"; const auto id = new GlImplData; ctx->setRendererData(id); - const auto vshad = ox::sfmt(bgvshad, GlslVersion); - const auto fshad = ox::sfmt(bgfshad, GlslVersion); + const auto vshad = ox::sfmt(bgvshad, glutils::GlslVersion); + const auto fshad = ox::sfmt(bgfshad, glutils::GlslVersion); oxReturnError(glutils::buildShaderProgram(vshad.c_str(), fshad.c_str()).moveTo(&id->bgShader)); for (auto &bg : id->backgrounds) { initBackgroundBufferset(ctx, id->bgShader, &bg); } - ImGui_ImplOpenGL3_Init(GlslVersion); + ImGui_ImplOpenGL3_Init(glutils::GlslVersion); return OxError(0); } @@ -280,8 +255,6 @@ void draw(Context *ctx) noexcept { glClear(GL_COLOR_BUFFER_BIT); // render renderer::drawBackgrounds(id); - //bool showDemo = true; - //ImGui::ShowDemoWindow(&showDemo); for (const auto cd : ctx->drawers) { cd->draw(ctx); } @@ -318,9 +291,10 @@ void setTile(Context *ctx, int layer, int column, int row, uint8_t tile) noexcep const auto x = static_cast(column); const auto i = renderer::bgVertexRow(x, y); auto &bg = id->backgrounds[z]; - auto vbo = &bg.bgVertices[i * renderer::BgVertexVboLength]; - auto ebo = &bg.bgElements[i * renderer::BgVertexEboLength]; - renderer::setTileBufferObject(ctx, i * renderer::BgVertexVboRows, static_cast(x), static_cast(y), tile, vbo, ebo); + auto vbo = &bg.vertices[i * renderer::BgVertexVboLength]; + auto ebo = &bg.elements[i * renderer::BgVertexEboLength]; + renderer::setTileBufferObject(ctx, i * renderer::BgVertexVboRows, + static_cast(x), static_cast(y), tile, vbo, ebo); bg.updated = true; } diff --git a/src/nostalgia/glutils/glutils.cpp b/src/nostalgia/glutils/glutils.cpp index ac07616b..22d52e53 100644 --- a/src/nostalgia/glutils/glutils.cpp +++ b/src/nostalgia/glutils/glutils.cpp @@ -67,8 +67,26 @@ ox::Result buildShaderProgram(const GLchar *vert, const GLchar *frag) return prgm; } +ox::Result buildShaderProgram(const ox::String &vert, const ox::String &frag) noexcept { + return buildShaderProgram(vert.c_str(), frag.c_str()); +} + +GLVertexArray generateVertexArrayObject() noexcept { + GLVertexArray vao; + glGenVertexArrays(1, &vao.id); + return vao; +} + +GLBuffer generateBuffer() noexcept { + GLBuffer buff; + glGenBuffers(1, &buff.id); + return buff; +} + FrameBuffer generateFrameBuffer(int width, int height) noexcept { FrameBuffer fb; + fb.width = width; + fb.height = height; glGenFramebuffers(1, &fb.fbo.id); glBindFramebuffer(GL_FRAMEBUFFER, fb); // color texture @@ -82,12 +100,25 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept { glGenRenderbuffers(1, &fb.depth.id); glBindRenderbuffer(GL_RENDERBUFFER, fb.depth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb.depth, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb.depth); // verify FBO oxAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame Buffer is incomplete"); // restore primary FB glBindFramebuffer(GL_FRAMEBUFFER, 0); + oxAssert(glGetError() == 0, "Framebuffer creation failed"); return fb; } +void sendVbo(const BufferSet &bg) noexcept { + const auto bufferSize = static_cast(sizeof(decltype(bg.vertices)::value_type) * bg.vertices.size()); + glBindBuffer(GL_ARRAY_BUFFER, bg.vbo); + glBufferData(GL_ARRAY_BUFFER, bufferSize, bg.vertices.data(), GL_DYNAMIC_DRAW); +} + +void sendEbo(const BufferSet &bg) noexcept { + const auto bufferSize = static_cast(sizeof(decltype(bg.elements)::value_type) * bg.elements.size()); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bg.ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, bg.elements.data(), GL_STATIC_DRAW); +} + } diff --git a/src/nostalgia/glutils/glutils.hpp b/src/nostalgia/glutils/glutils.hpp index f1006899..5028cca8 100644 --- a/src/nostalgia/glutils/glutils.hpp +++ b/src/nostalgia/glutils/glutils.hpp @@ -9,6 +9,7 @@ #pragma once #include +#include #define GL_GLEXT_PROTOTYPES 1 #ifdef OX_OS_Darwin @@ -21,9 +22,12 @@ #endif #include +#include namespace nostalgia::glutils { +constexpr auto GlslVersion = "#version 150"; + struct Empty {}; struct TextureBase { @@ -125,6 +129,8 @@ using GLVertexArray = GLObject; * and not its dependencies. */ struct FrameBuffer { + int width = 0; + int height = 0; GLFrameBuffer fbo; GLTexture color; GLRenderBuffer depth; @@ -139,10 +145,28 @@ struct FrameBuffer { }; -[[nodiscard]] ox::Result buildShaderProgram(const GLchar *vert, const GLchar *frag) noexcept; +ox::Result buildShaderProgram(const ox::String &vert, const ox::String &frag) noexcept; + +glutils::GLVertexArray generateVertexArrayObject() noexcept; + +glutils::GLBuffer generateBuffer() noexcept; + [[nodiscard]] FrameBuffer generateFrameBuffer(int width, int height) noexcept; -} \ No newline at end of file +struct BufferSet { + glutils::GLVertexArray vao; + glutils::GLBuffer vbo; + glutils::GLBuffer ebo; + glutils::GLTexture tex; + ox::Vector vertices; + ox::Vector elements; +}; + +void sendVbo(const BufferSet &bg) noexcept; + +void sendEbo(const BufferSet &bg) noexcept; + +}