#include "glad/glad.h" #include #include #include #include #include // SDL for window size query #include namespace extra2d { RendererModule::RendererModule() = default; RendererModule::~RendererModule() = default; RendererModule::RendererModule(RendererModule &&other) noexcept : materialPool_(std::move(other.materialPool_)), meshPool_(std::move(other.meshPool_)), texturePool_(std::move(other.texturePool_)), commandBuffer_(std::move(other.commandBuffer_)), commandCount_(other.commandCount_), uniformManager_(std::move(other.uniformManager_)), defaultMaterialHandle_(other.defaultMaterialHandle_), defaultQuadHandle_(other.defaultQuadHandle_), defaultTextureHandle_(other.defaultTextureHandle_), onRenderBeginListener_(std::move(other.onRenderBeginListener_)), onRenderSubmitListener_(std::move(other.onRenderSubmitListener_)), onRenderEndListener_(std::move(other.onRenderEndListener_)), onResizeListener_(std::move(other.onResizeListener_)), onShowListener_(std::move(other.onShowListener_)), glInitialized_(other.glInitialized_), stats_(other.stats_), viewportX_(other.viewportX_), viewportY_(other.viewportY_), viewportWidth_(other.viewportWidth_), viewportHeight_(other.viewportHeight_) { // 重置源对象状态 other.commandCount_ = 0; other.defaultMaterialHandle_ = INVALID_MATERIAL_HANDLE; other.defaultQuadHandle_ = INVALID_MESH_HANDLE; other.defaultTextureHandle_ = INVALID_TEXTURE_HANDLE; other.glInitialized_ = false; other.stats_ = {}; other.viewportX_ = 0; other.viewportY_ = 0; other.viewportWidth_ = 0; other.viewportHeight_ = 0; } RendererModule &RendererModule::operator=(RendererModule &&other) noexcept { if (this != &other) { // 清理当前资源 if (glInitialized_) { destroyDefaultResources(); uniformManager_.shutdown(); } // 移动资源 materialPool_ = std::move(other.materialPool_); meshPool_ = std::move(other.meshPool_); texturePool_ = std::move(other.texturePool_); commandBuffer_ = std::move(other.commandBuffer_); commandCount_ = other.commandCount_; uniformManager_ = std::move(other.uniformManager_); defaultMaterialHandle_ = other.defaultMaterialHandle_; defaultQuadHandle_ = other.defaultQuadHandle_; defaultTextureHandle_ = other.defaultTextureHandle_; onRenderBeginListener_ = std::move(other.onRenderBeginListener_); onRenderSubmitListener_ = std::move(other.onRenderSubmitListener_); onRenderEndListener_ = std::move(other.onRenderEndListener_); onResizeListener_ = std::move(other.onResizeListener_); onShowListener_ = std::move(other.onShowListener_); glInitialized_ = other.glInitialized_; stats_ = other.stats_; viewportX_ = other.viewportX_; viewportY_ = other.viewportY_; viewportWidth_ = other.viewportWidth_; viewportHeight_ = other.viewportHeight_; // 重置源对象状态 other.commandCount_ = 0; other.defaultMaterialHandle_ = INVALID_MATERIAL_HANDLE; other.defaultQuadHandle_ = INVALID_MESH_HANDLE; other.defaultTextureHandle_ = INVALID_TEXTURE_HANDLE; other.glInitialized_ = false; other.stats_ = {}; other.viewportX_ = 0; other.viewportY_ = 0; other.viewportWidth_ = 0; other.viewportHeight_ = 0; } return *this; } bool RendererModule::init() { E2D_LOG_INFO("Initializing RendererModule..."); // 绑定事件监听器 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_t w, int32_t h) { onResize(w, h); }); // 延迟 GL 初始化到窗口显示时 onShowListener_.bind([this]() { onWindowShow(); }); E2D_LOG_INFO("RendererModule initialized (waiting for GL context)"); return true; } void RendererModule::onWindowShow() { if (glInitialized_) { return; } E2D_LOG_INFO("Initializing OpenGL context..."); // 初始化 UBO 管理器(需要 GL 上下文) if (!uniformManager_.initialize()) { E2D_LOG_ERROR("Failed to initialize UniformBufferManager"); return; } // 创建默认资源(需要 GL 上下文) if (!createDefaultResources()) { E2D_LOG_ERROR("Failed to create default resources"); return; } // 获取实际窗口大小并设置视口 // 查询当前 SDL 窗口大小 int windowWidth = 800, windowHeight = 600; SDL_Window *sdlWindow = SDL_GL_GetCurrentWindow(); if (sdlWindow) { SDL_GetWindowSize(sdlWindow, &windowWidth, &windowHeight); E2D_LOG_INFO("Setting initial viewport to window size: {}x{}", windowWidth, windowHeight); } else { E2D_LOG_WARN("Could not get SDL window, using default viewport 800x600"); } setViewport(0, 0, static_cast(windowWidth), static_cast(windowHeight)); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glInitialized_ = true; E2D_LOG_INFO("OpenGL context initialized successfully"); } void RendererModule::shutdown() { E2D_LOG_INFO("Shutting down RendererModule..."); // 只有在 GL 初始化后才销毁 GL 相关资源 if (glInitialized_) { // 销毁默认资源 destroyDefaultResources(); // 关闭 UBO 管理器 uniformManager_.shutdown(); } // 清理资源池 materialPool_.slots.clear(); while (!materialPool_.freeIndices.empty()) materialPool_.freeIndices.pop(); meshPool_.slots.clear(); while (!meshPool_.freeIndices.empty()) meshPool_.freeIndices.pop(); texturePool_.slots.clear(); while (!texturePool_.freeIndices.empty()) texturePool_.freeIndices.pop(); glInitialized_ = false; E2D_LOG_INFO("RendererModule shutdown complete"); } MaterialHandle RendererModule::registerMaterial(Ptr material) { uint64_t handle = materialPool_.acquire(); auto *slot = materialPool_.get(handle); if (slot) { slot->material = material; } return handle; } MeshHandle RendererModule::registerMesh(Ptr mesh) { uint64_t handle = meshPool_.acquire(); auto *slot = meshPool_.get(handle); if (slot) { slot->mesh = mesh; } return handle; } TextureHandle RendererModule::registerTexture(Ptr texture) { uint64_t handle = texturePool_.acquire(); auto *slot = texturePool_.get(handle); if (slot) { slot->texture = texture; } return handle; } void RendererModule::unregisterMaterial(MaterialHandle handle) { materialPool_.release(handle); } void RendererModule::unregisterMesh(MeshHandle handle) { meshPool_.release(handle); } void RendererModule::unregisterTexture(TextureHandle handle) { texturePool_.release(handle); } Ptr RendererModule::getMaterial(MaterialHandle handle) { auto *slot = materialPool_.get(handle); return slot ? slot->material : nullptr; } Ptr RendererModule::getMesh(MeshHandle handle) { auto *slot = meshPool_.get(handle); return slot ? slot->mesh : nullptr; } Ptr RendererModule::getTexture(TextureHandle handle) { auto *slot = texturePool_.get(handle); return slot ? slot->texture : nullptr; } void RendererModule::setViewport(int32 x, int32 y, int32 width, int32 height) { viewportX_ = x; viewportY_ = y; viewportWidth_ = width; viewportHeight_ = height; // 更新视口适配器 viewportAdapter_.update(width, height); // 获取适配后的视口 auto result = viewportAdapter_.getResult(); glViewport(static_cast(result.viewport.x), static_cast(result.viewport.y), static_cast(result.viewport.w), static_cast(result.viewport.h)); } void RendererModule::clear(const Color &color, uint32_t flags) { GLbitfield mask = 0; if (flags & CLEAR_COLOR_FLAG) { glClearColor(color.r, color.g, color.b, color.a); mask |= GL_COLOR_BUFFER_BIT; } if (flags & CLEAR_DEPTH_FLAG) { mask |= GL_DEPTH_BUFFER_BIT; } if (flags & CLEAR_STENCIL_FLAG) { mask |= GL_STENCIL_BUFFER_BIT; } if (mask != 0) { glClear(mask); } } void RendererModule::onRenderBegin() { // 如果 GL 未初始化,跳过渲染 if (!glInitialized_) { return; } // 清除屏幕(黑色背景) glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // 清空命令缓冲区 commandCount_ = 0; // 重置统计 stats_ = {}; // 重置 UBO 管理器 uniformManager_.resetMaterialUBOs(); } void RendererModule::onRenderSubmit(const RenderCommand &cmd) { // 如果 GL 未初始化,跳过提交 if (!glInitialized_) { return; } // 检查缓冲区是否已满 if (commandCount_ >= MAX_RENDER_COMMANDS) { E2D_LOG_WARN("Render command buffer full!"); return; } // 直接存入预分配缓冲区(无动态分配) commandBuffer_[commandCount_++] = cmd; stats_.commandsSubmitted++; } void RendererModule::onRenderSetCamera(const Mat4 &viewProj) { // 如果 GL 未初始化,跳过 if (!glInitialized_) { return; } // 保存视图投影矩阵 viewProjectionMatrix_ = viewProj; // 更新全局 UBO 中的视图投影矩阵 uniformManager_.updateGlobalUBO(&viewProj, sizeof(Mat4)); } void RendererModule::onRenderEnd() { // 如果 GL 未初始化,跳过渲染 if (!glInitialized_) { return; } // 排序命令 sortCommands(); // 批处理并绘制 batchAndDraw(); // 输出统计 E2D_LOG_DEBUG("Render: {} commands, {} draw calls, {} batches", stats_.commandsExecuted, stats_.drawCalls, stats_.batches); } void RendererModule::onResize(int32 width, int32 height) { setViewport(0, 0, width, height); } void RendererModule::sortCommands() { // 使用 std::sort 对命令进行排序 std::sort(commandBuffer_.begin(), commandBuffer_.begin() + commandCount_, [](const RenderCommand &a, const RenderCommand &b) { return a.sortKey < b.sortKey; }); } void RendererModule::batchAndDraw() { MaterialHandle lastMaterial = INVALID_MATERIAL_HANDLE; MeshHandle lastMesh = INVALID_MESH_HANDLE; uint32_t batchStart = 0; uint32_t batchCount = 0; for (uint32_t i = 0; i < commandCount_; ++i) { const auto &cmd = commandBuffer_[i]; if (cmd.type != RenderCommandType::DrawMesh) { // 处理非绘制命令 if (batchCount > 0) { drawBatch(batchStart, batchCount, lastMaterial, lastMesh); stats_.batches++; batchCount = 0; } executeCommand(cmd); continue; } // 检查是否需要刷新批次 if (cmd.drawMesh.material != lastMaterial || cmd.drawMesh.mesh != lastMesh) { // 刷新上一批次 if (batchCount > 0) { drawBatch(batchStart, batchCount, lastMaterial, lastMesh); stats_.batches++; } lastMaterial = cmd.drawMesh.material; lastMesh = cmd.drawMesh.mesh; batchStart = i; batchCount = 1; } else { ++batchCount; } stats_.commandsExecuted++; } // 刷新最后一批 if (batchCount > 0) { drawBatch(batchStart, batchCount, lastMaterial, lastMesh); stats_.batches++; } } void RendererModule::drawBatch(uint32_t start, uint32_t count, MaterialHandle materialHandle, MeshHandle meshHandle) { auto material = getMaterial(materialHandle); // 如果材质无效,使用默认材质 if (!material) { material = getMaterial(defaultMaterialHandle_); } auto mesh = getMesh(meshHandle); // 如果网格无效,使用默认四边形 if (!mesh) { mesh = getMesh(defaultQuadHandle_); } if (!material || !mesh) return; // 获取着色器 auto shader = material->getShader(); if (!shader) return; // 绑定着色器 shader->bind(); // 设置视图投影矩阵 shader->setMat4("uViewProjection", glm::value_ptr(viewProjectionMatrix_)); // 设置材质参数 // 注意:直接使用默认值,因为材质数据布局可能不匹配 // tintColor 和 opacity 由着色器默认值处理 shader->setVec4("uTintColor", 1.0f, 1.0f, 1.0f, 1.0f); shader->setFloat("uOpacity", 1.0f); // 绑定材质中的纹理 const auto &textureSlots = material->getTextures(); bool hasMaterialTexture = false; for (const auto &slot : textureSlots) { if (slot.handle != INVALID_TEXTURE_HANDLE) { auto texture = getTexture(slot.handle); if (texture) { texture->bind(slot.slot); // 设置采样器 uniform shader->setInt(slot.uniformName, static_cast(slot.slot)); hasMaterialTexture = true; } } } // 如果材质没有纹理,绑定默认纹理 if (!hasMaterialTexture && defaultTextureHandle_ != INVALID_TEXTURE_HANDLE) { auto defaultTexture = getTexture(defaultTextureHandle_); if (defaultTexture) { defaultTexture->bind(0); shader->setInt("uTexture", 0); } } // 绑定网格 mesh->bind(); // 对每个实例单独绘制 for (uint32_t i = 0; i < count; ++i) { Transform transform = commandBuffer_[start + i].getTransform(); float matrix[16]; transform.toMatrix(matrix); // 设置模型矩阵 shader->setMat4("uModelMatrix", matrix); // 设置顶点颜色 Color color = commandBuffer_[start + i].getColor(); shader->setVec4("uColor", color.r, color.g, color.b, color.a); // 绘制 mesh->draw(); stats_.drawCalls++; } } void RendererModule::executeCommand(const RenderCommand &cmd) { 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; } } bool RendererModule::createDefaultResources() { // 创建默认着色器 auto defaultShader = makePtr(); if (!defaultShader->loadFromFile("shader/default.vert", "shader/default.frag")) { E2D_LOG_ERROR("Failed to load default shader"); return false; } // 创建默认材质布局 auto defaultLayout = makePtr(); defaultLayout->addParam("tintColor", MaterialParamType::Color); defaultLayout->addParam("opacity", MaterialParamType::Float); defaultLayout->finalize(); // 创建默认材质 auto defaultMaterial = makePtr(); defaultMaterial->setLayout(defaultLayout); defaultMaterial->setShader(defaultShader); defaultMaterial->setColor("tintColor", Color::White); defaultMaterial->setFloat("opacity", 1.0f); defaultMaterialHandle_ = registerMaterial(defaultMaterial); // 创建默认四边形 auto defaultQuad = Mesh::createQuad(Vec2(1.0f, 1.0f)); defaultQuadHandle_ = registerMesh(defaultQuad); // 创建默认纹理(1x1 白色) auto defaultTexture = makePtr(); uint8_t whitePixel[4] = {255, 255, 255, 255}; defaultTexture->loadFromMemory(whitePixel, 1, 1, TextureFormat::RGBA8); defaultTextureHandle_ = registerTexture(defaultTexture); E2D_LOG_INFO("Default resources created"); return true; } void RendererModule::destroyDefaultResources() { if (defaultMaterialHandle_ != INVALID_MATERIAL_HANDLE) { unregisterMaterial(defaultMaterialHandle_); defaultMaterialHandle_ = INVALID_MATERIAL_HANDLE; } if (defaultQuadHandle_ != INVALID_MESH_HANDLE) { unregisterMesh(defaultQuadHandle_); defaultQuadHandle_ = INVALID_MESH_HANDLE; } if (defaultTextureHandle_ != INVALID_TEXTURE_HANDLE) { unregisterTexture(defaultTextureHandle_); defaultTextureHandle_ = INVALID_TEXTURE_HANDLE; } } } // namespace extra2d