feat(渲染): 重构渲染系统并添加相机支持
- 在Batch中添加纹理采样器uniform设置 - 重构Sprite渲染逻辑,使用Renderer的drawSprite方法 - 添加Camera类并集成到Application和Renderer中 - 支持Y轴翻转的投影矩阵以适应2D游戏坐标系 - 改进颜色处理,移除不必要的归一化计算 - 添加渲染错误处理和日志输出
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <frostbite2D/core/window.h>
|
||||
#include <frostbite2D/graphics/camera.h>
|
||||
#include <frostbite2D/types/type_alias.h>
|
||||
#include <string>
|
||||
|
||||
@@ -176,6 +177,7 @@ private:
|
||||
|
||||
Window* window_ = nullptr;
|
||||
class Renderer* renderer_ = nullptr;
|
||||
Camera* camera_ = nullptr;
|
||||
AppConfig config_;
|
||||
|
||||
bool initialized_ = false;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <cstdio>
|
||||
#include <frostbite2D/core/application.h>
|
||||
#include <frostbite2D/graphics/renderer.h>
|
||||
#include <frostbite2D/graphics/camera.h>
|
||||
#include <frostbite2D/platform/switch.h>
|
||||
#include <frostbite2D/types/type_math.h>
|
||||
#include <frostbite2D/utils/asset.h>
|
||||
@@ -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();
|
||||
|
||||
@@ -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_);
|
||||
|
||||
@@ -37,8 +37,19 @@ glm::mat4 Camera::getViewMatrix() const {
|
||||
glm::mat4 Camera::getProjectionMatrix() const {
|
||||
float left = 0.0f;
|
||||
float right = static_cast<float>(viewportWidth_);
|
||||
float bottom = static_cast<float>(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<float>(viewportHeight_);
|
||||
top = 0.0f;
|
||||
} else {
|
||||
// Y 轴向上:(0,0) 在左下角(OpenGL 默认)
|
||||
bottom = 0.0f;
|
||||
top = static_cast<float>(viewportHeight_);
|
||||
}
|
||||
|
||||
return glm::ortho(left, right, bottom, top, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
@@ -175,10 +175,7 @@ void Renderer::drawQuad(const Vec2& pos, const Size& size, Ptr<Texture> texture)
|
||||
void Renderer::drawQuad(const Rect& rect, const Color& color) {
|
||||
drawQuad(Vec2(rect.left(), rect.top()),
|
||||
Size(rect.width(), rect.height()),
|
||||
static_cast<float>(color.r) / 255.0f,
|
||||
static_cast<float>(color.g) / 255.0f,
|
||||
static_cast<float>(color.b) / 255.0f,
|
||||
static_cast<float>(color.a) / 255.0f);
|
||||
color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
void Renderer::drawSprite(const Vec2& pos, const Size& size, Ptr<Texture> texture) {
|
||||
@@ -189,10 +186,7 @@ void Renderer::drawSprite(const Vec2& pos, const Rect& srcRect, const Vec2& texS
|
||||
Ptr<Texture> texture, const Color& color) {
|
||||
Rect destRect(pos.x, pos.y, srcRect.width(), srcRect.height());
|
||||
Quad quad = Quad::createTextured(destRect, srcRect, texSize,
|
||||
static_cast<float>(color.r) / 255.0f,
|
||||
static_cast<float>(color.g) / 255.0f,
|
||||
static_cast<float>(color.b) / 255.0f,
|
||||
static_cast<float>(color.a) / 255.0f);
|
||||
color.r, color.g, color.b, color.a);
|
||||
Transform2D transform = Transform2D::identity();
|
||||
|
||||
auto* shader = shaderManager_.getShader("sprite");
|
||||
|
||||
@@ -32,9 +32,18 @@ int main(int argc, char **argv) {
|
||||
auto menuScene = MakePtr<Scene>();
|
||||
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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user