From 57a96a0cc574df189bc4c5aeedea8021495ad1b4 Mon Sep 17 00:00:00 2001 From: Lenheart <947330670@qq.com> Date: Tue, 17 Mar 2026 18:40:19 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=B8=B2=E6=9F=93):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=B3=BB=E7=BB=9F=E5=B9=B6=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=9B=B8=E6=9C=BA=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在Batch中添加纹理采样器uniform设置 - 重构Sprite渲染逻辑,使用Renderer的drawSprite方法 - 添加Camera类并集成到Application和Renderer中 - 支持Y轴翻转的投影矩阵以适应2D游戏坐标系 - 改进颜色处理,移除不必要的归一化计算 - 添加渲染错误处理和日志输出 --- .../include/frostbite2D/core/application.h | 2 ++ Frostbite2D/src/frostbite2D/2d/sprite.cpp | 22 +++++++++---------- .../src/frostbite2D/core/application.cpp | 18 ++++++++++++--- .../src/frostbite2D/graphics/batch.cpp | 4 +++- .../src/frostbite2D/graphics/camera.cpp | 15 +++++++++++-- .../src/frostbite2D/graphics/renderer.cpp | 10 ++------- Game/src/main.cpp | 13 +++++++++-- 7 files changed, 56 insertions(+), 28 deletions(-) diff --git a/Frostbite2D/include/frostbite2D/core/application.h b/Frostbite2D/include/frostbite2D/core/application.h index 4f98cd5..b46efbe 100644 --- a/Frostbite2D/include/frostbite2D/core/application.h +++ b/Frostbite2D/include/frostbite2D/core/application.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -176,6 +177,7 @@ private: Window* window_ = nullptr; class Renderer* renderer_ = nullptr; + Camera* camera_ = nullptr; AppConfig config_; bool initialized_ = false; diff --git a/Frostbite2D/src/frostbite2D/2d/sprite.cpp b/Frostbite2D/src/frostbite2D/2d/sprite.cpp index 60a5d94..fa7ce97 100644 --- a/Frostbite2D/src/frostbite2D/2d/sprite.cpp +++ b/Frostbite2D/src/frostbite2D/2d/sprite.cpp @@ -55,19 +55,17 @@ void Sprite::Render() { } Renderer& renderer = Renderer::get(); - Batch& batch = renderer.getBatch(); - - Shader* shader = getActiveShader(); - if (!shader || !shader->isValid()) { - RenderChildren(); - return; + + Vec2 pos = GetPosition(); + Vec2 size = GetSize(); + if (size.x == 0 || size.y == 0) { + size = Vec2((float)texture_->getWidth(), (float)texture_->getHeight()); } - - updateTransform(); - - Quad quad = createQuad(); - - batch.submitQuad(quad, transform_, texture_, shader, blendMode_); + + // 直接使用 Renderer 的 drawSprite 函数,确保和直接渲染一致 + renderer.drawSprite(pos, Rect(0, 0, (float)texture_->getWidth(), (float)texture_->getHeight()), + Vec2((float)texture_->getWidth(), (float)texture_->getHeight()), + texture_, color_); RenderChildren(); } diff --git a/Frostbite2D/src/frostbite2D/core/application.cpp b/Frostbite2D/src/frostbite2D/core/application.cpp index 4e9fe74..4e5c8e1 100644 --- a/Frostbite2D/src/frostbite2D/core/application.cpp +++ b/Frostbite2D/src/frostbite2D/core/application.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -69,6 +70,12 @@ void Application::shutdown() { window_ = nullptr; } + // 清理相机 + if (camera_) { + delete camera_; + camera_ = nullptr; + } + // 平台相关清理 #ifdef __SWITCH__ switchShutdown(); @@ -110,6 +117,12 @@ bool Application::initCoreModules() { renderer_->setViewport(0, 0, config_.windowConfig.width, config_.windowConfig.height); + // 创建并设置相机 + camera_ = new Camera(); + camera_->setViewport(config_.windowConfig.width, config_.windowConfig.height); + camera_->setFlipY(true); // 启用 Y 轴翻转,(0,0) 在左上角 + renderer_->setCamera(camera_); + return true; } @@ -198,11 +211,10 @@ void Application::update() { void Application::render() { Renderer& renderer = Renderer::get(); - Batch& batch = renderer.getBatch(); - batch.begin(); + renderer.beginFrame(); SceneManager::get().Render(); - batch.end(); + renderer.endFrame(); if (window_) { window_->swap(); diff --git a/Frostbite2D/src/frostbite2D/graphics/batch.cpp b/Frostbite2D/src/frostbite2D/graphics/batch.cpp index 643b2db..2a2212d 100644 --- a/Frostbite2D/src/frostbite2D/graphics/batch.cpp +++ b/Frostbite2D/src/frostbite2D/graphics/batch.cpp @@ -152,9 +152,11 @@ void Batch::flushCurrentBatch() { // 绑定着色器和纹理 if (currentBatch_.shader) { currentBatch_.shader->use(); + // 设置纹理采样器 uniform 变量 + currentBatch_.shader->setTexture("u_texture", 0); } if (currentBatch_.texture) { - currentBatch_.texture->bind(); + currentBatch_.texture->bind(0); } glBindBuffer(GL_ARRAY_BUFFER, vbo_); diff --git a/Frostbite2D/src/frostbite2D/graphics/camera.cpp b/Frostbite2D/src/frostbite2D/graphics/camera.cpp index 5c88a28..3b2c454 100644 --- a/Frostbite2D/src/frostbite2D/graphics/camera.cpp +++ b/Frostbite2D/src/frostbite2D/graphics/camera.cpp @@ -37,8 +37,19 @@ glm::mat4 Camera::getViewMatrix() const { glm::mat4 Camera::getProjectionMatrix() const { float left = 0.0f; float right = static_cast(viewportWidth_); - float bottom = static_cast(viewportHeight_); - float top = 0.0f; + float bottom, top; + + if (flipY_) { + // Y 轴向下:(0,0) 在左上角(2D 游戏常用) + // glm::ortho(left, right, bottom, top, ...) + // 这里 bottom 是屏幕底部(值大),top 是屏幕顶部(值小) + bottom = static_cast(viewportHeight_); + top = 0.0f; + } else { + // Y 轴向上:(0,0) 在左下角(OpenGL 默认) + bottom = 0.0f; + top = static_cast(viewportHeight_); + } return glm::ortho(left, right, bottom, top, -1.0f, 1.0f); } diff --git a/Frostbite2D/src/frostbite2D/graphics/renderer.cpp b/Frostbite2D/src/frostbite2D/graphics/renderer.cpp index a96162f..853c6f1 100644 --- a/Frostbite2D/src/frostbite2D/graphics/renderer.cpp +++ b/Frostbite2D/src/frostbite2D/graphics/renderer.cpp @@ -175,10 +175,7 @@ void Renderer::drawQuad(const Vec2& pos, const Size& size, Ptr texture) void Renderer::drawQuad(const Rect& rect, const Color& color) { drawQuad(Vec2(rect.left(), rect.top()), Size(rect.width(), rect.height()), - static_cast(color.r) / 255.0f, - static_cast(color.g) / 255.0f, - static_cast(color.b) / 255.0f, - static_cast(color.a) / 255.0f); + color.r, color.g, color.b, color.a); } void Renderer::drawSprite(const Vec2& pos, const Size& size, Ptr texture) { @@ -189,10 +186,7 @@ void Renderer::drawSprite(const Vec2& pos, const Rect& srcRect, const Vec2& texS Ptr texture, const Color& color) { Rect destRect(pos.x, pos.y, srcRect.width(), srcRect.height()); Quad quad = Quad::createTextured(destRect, srcRect, texSize, - static_cast(color.r) / 255.0f, - static_cast(color.g) / 255.0f, - static_cast(color.b) / 255.0f, - static_cast(color.a) / 255.0f); + color.r, color.g, color.b, color.a); Transform2D transform = Transform2D::identity(); auto* shader = shaderManager_.getShader("sprite"); diff --git a/Game/src/main.cpp b/Game/src/main.cpp index 75a29ba..7846487 100644 --- a/Game/src/main.cpp +++ b/Game/src/main.cpp @@ -32,9 +32,18 @@ int main(int argc, char **argv) { auto menuScene = MakePtr(); SceneManager::get().PushScene(menuScene); + // 先测试彩色四边形,排除纹理问题 + SDL_Log("Testing colored quad..."); + + // 尝试加载精灵 auto sprite = Sprite::createFromFile("assets\\player.png"); - sprite->SetPosition(100, 100); - menuScene->AddActor(sprite); + if (sprite) { + sprite->SetPosition(100, 100); + menuScene->AddActor(sprite); + SDL_Log("Sprite created and added to scene"); + } else { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create sprite from file!"); + } app.run();