Extra2D/src/renderer/renderer_module.cpp

277 lines
7.6 KiB
C++
Raw Normal View History

#include <assets/assets_module.h>
#include <platform/window_module.h>
#include <renderer/render_graph.h>
#include <renderer/renderer_module.h>
#include <renderer/rhi_module.h>
#include <utils/logger.h>
namespace extra2d {
RendererModule::RendererModule() = default;
RendererModule::~RendererModule() = default;
bool RendererModule::init() {
E2D_LOG_INFO("正在初始化渲染模块...");
// 绑定事件监听器
onRenderBeginListener_.bind([this]() { onRenderBegin(); });
onRenderSubmitListener_.bind(
[this](const RenderCommand &cmd) { onRenderSubmit(cmd); });
onRenderSetCameraListener_.bind(
[this](const Mat4 &viewProj) { onRenderSetCamera(viewProj); });
onRenderEndListener_.bind([this]() { onRenderEnd(); });
onResizeListener_.bind([this](int32 w, int32 h) { onResize(w, h); });
onShowListener_.bind([this]() { onWindowShow(); });
E2D_LOG_INFO("渲染模块已初始化 (等待窗口显示)");
return true;
}
void RendererModule::onWindowShow() {
if (initialized_) {
return;
}
E2D_LOG_INFO("正在初始化渲染模块上下文...");
// 初始化 RHI 模块
auto *rhiModule = RHIModule::get();
if (!rhiModule) {
E2D_LOG_ERROR("RHI 模块不可用");
return;
}
if (!rhiModule->getDevice()) {
// RHI 设备尚未初始化,这是正常的时序问题
// RHIModule 会在窗口显示后初始化设备,然后再次触发此函数
E2D_LOG_INFO("RHI 设备尚未就绪,等待 RHI 初始化...");
return;
}
// 初始化渲染图
if (!renderGraph_.initialize()) {
E2D_LOG_ERROR("初始化渲染图失败");
return;
}
commandQueue_ = renderGraph_.getCommandQueue();
// 添加默认的几何渲染通道
auto geometryPass = std::make_unique<GeometryRenderPass>("Geometry");
renderGraph_.addPass(std::move(geometryPass));
E2D_LOG_INFO("已添加默认几何渲染通道");
auto windowModule = getModule<WindowModule>();
if (!windowModule) {
E2D_LOG_ERROR("窗口模块不可用");
return;
}
setViewport(0, 0, static_cast<int32>(windowModule->getSize().w),
static_cast<int32>(windowModule->getSize().h));
initialized_ = true;
E2D_LOG_INFO("渲染模块上下文初始化成功");
}
void RendererModule::shutdown() {
E2D_LOG_INFO("正在关闭渲染模块...");
renderGraph_.shutdown();
commandQueue_ = nullptr;
initialized_ = false;
// 注意:事件监听器是值类型,会在析构时自动清理
E2D_LOG_INFO("渲染模块关闭完成");
}
RHIContext *RendererModule::getRHIContext() const {
auto *rhiModule = RHIModule::get();
if (rhiModule && rhiModule->getDevice()) {
return rhiModule->getDevice()->getContext();
}
return nullptr;
}
Handle<Material> RendererModule::getDefaultMaterialHandle() const {
auto *assets = getAssets();
return assets ? assets->getDefaultMaterial() : Handle<Material>::invalid();
}
Handle<Mesh> RendererModule::getDefaultQuadHandle() const {
auto *assets = getAssets();
return assets ? assets->getDefaultQuad() : Handle<Mesh>::invalid();
}
Handle<Texture> RendererModule::getDefaultTextureHandle() const {
auto *assets = getAssets();
return assets ? assets->getDefaultTexture() : Handle<Texture>::invalid();
}
void RendererModule::setViewport(int32 x, int32 y, int32 width, int32 height) {
viewportX_ = x;
viewportY_ = y;
viewportWidth_ = width;
viewportHeight_ = height;
viewportAdapter_.update(width, height);
// 更新渲染图输出尺寸
renderGraph_.setOutputSize(static_cast<uint32_t>(width),
static_cast<uint32_t>(height));
// 通过 RHI 设置视口
if (initialized_) {
auto *context = getRHIContext();
if (context) {
auto result = viewportAdapter_.getResult();
context->setViewport(static_cast<int32_t>(result.viewport.x),
static_cast<int32_t>(result.viewport.y),
static_cast<uint32_t>(result.viewport.w),
static_cast<uint32_t>(result.viewport.h));
}
}
}
void RendererModule::clear(const Color &color, uint32 flags) {
if (!initialized_)
return;
if (commandQueue_) {
commandQueue_->submitClear(color, flags);
}
}
void RendererModule::onRenderBegin() {
if (!initialized_) {
return;
}
// 重置统计
stats_ = {};
// 开始渲染帧 - 清空命令队列准备接收新的渲染命令
if (commandQueue_) {
commandQueue_->beginFrame();
}
// 帧开始
}
void RendererModule::onRenderSubmit(const RenderCommand &cmd) {
if (!initialized_ || !commandQueue_) {
E2D_LOG_WARN("onRenderSubmit: 渲染模块未初始化或没有命令队列");
return;
}
(void)cmd; // 避免未使用警告
// 将渲染命令转换为绘制命令提交到队列
switch (cmd.type) {
case RenderCommandType::DrawMesh: {
auto *assets = getAssets();
if (!assets)
return;
// 获取材质,如果没有指定则使用默认材质
Material *material = assets->get(cmd.drawMesh.material);
if (!material) {
material = assets->get(assets->getDefaultMaterial());
}
// 获取网格,如果没有指定则使用默认四边形
Mesh *mesh = assets->get(cmd.drawMesh.mesh);
if (!mesh) {
mesh = assets->get(assets->getDefaultQuad());
}
if (material && mesh) {
Transform transform(cmd.drawMesh.pos, cmd.drawMesh.scale,
cmd.drawMesh.rot);
commandQueue_->submitDraw(Ptr<Material>(material), Ptr<Mesh>(mesh),
transform, cmd.drawMesh.color);
stats_.commandsSubmitted++;
} else {
E2D_LOG_WARN("提交绘制命令失败: 材质={}, 网格={}",
material ? "有效" : "", mesh ? "有效" : "");
}
break;
}
case RenderCommandType::SetViewport: {
setViewport(cmd.viewport.x, cmd.viewport.y, cmd.viewport.width,
cmd.viewport.height);
break;
}
case RenderCommandType::Clear: {
clear(cmd.clear.color, cmd.clear.flags);
break;
}
}
}
void RendererModule::onRenderSetCamera(const Mat4 &viewProj) {
if (!initialized_) {
return;
}
viewProjectionMatrix_ = viewProj;
// 更新全局 UBO通过 RenderGraph 的命令队列)
// 实际的 UBO 更新会在 RenderGraph 执行时进行
}
void RendererModule::onRenderEnd() {
if (!initialized_) {
E2D_LOG_WARN("onRenderEnd: 渲染模块未初始化");
return;
}
// 执行渲染图,传递视图投影矩阵
renderGraph_.execute(0.016f, viewProjectionMatrix_);
// 获取统计信息
if (commandQueue_) {
const auto &stats = commandQueue_->getStats();
stats_.drawCalls = stats.drawCalls;
// 每60帧输出一次统计信息
static uint32_t frameCount = 0;
if (++frameCount % 60 == 0) {
E2D_LOG_INFO("渲染统计: 绘制调用={}, 三角形数={}, 顶点数={}, "
"管线绑定={}, 纹理绑定={}, 缓冲区绑定={}",
stats.drawCalls, stats.triangles, stats.vertices,
stats.pipelineBinds, stats.textureBinds, stats.bufferBinds);
}
}
// 渲染完成
}
void RendererModule::onResize(int32 width, int32 height) {
setViewport(0, 0, width, height);
}
void RendererModule::executeCommand(const RenderCommand &cmd) {
// 此方法保留用于直接执行特定命令
// 大部分命令现在通过 RenderGraph 处理
switch (cmd.type) {
case RenderCommandType::SetViewport:
setViewport(cmd.viewport.x, cmd.viewport.y, cmd.viewport.width,
cmd.viewport.height);
break;
case RenderCommandType::Clear:
clear(cmd.clear.color, cmd.clear.flags);
break;
default:
break;
}
}
} // namespace extra2d