#pragma once #include #include #include #include #include #include #include #include #include #include struct SDL_Window; namespace frostbite2D { // 混合模式枚举 enum class BlendMode { None, Alpha, Additive, Multiply }; // 渲染统计信息 struct RenderStats { uint32_t drawCalls = 0; uint32_t triangleCount = 0; }; // ============================================================================ // OpenGL 渲染器实现 // ============================================================================ class GLRenderer { public: GLRenderer(); ~GLRenderer(); /** * @brief 初始化OpenGL渲染器 * @param window SDL窗口指针 * @return 初始化成功返回true,失败返回false */ bool init(SDL_Window *window); /** * @brief 关闭渲染器,释放所有GPU资源 */ void shutdown(); /** * @brief 开始新帧,清除颜色缓冲区并重置统计信息 * @param clearColor 清屏颜色 */ void beginFrame(const Color &clearColor); /** * @brief 结束当前帧,刷新所有待处理的渲染批次 */ void endFrame(); /** * @brief 设置视口区域 * @param x 视口左下角X坐标 * @param y 视口左下角Y坐标 * @param width 视口宽度 * @param height 视口高度 */ void setViewport(int x, int y, int width, int height); /** * @brief 设置垂直同步 * @param enabled true启用垂直同步,false禁用 */ void setVSync(bool enabled); /** * @brief 设置混合模式 * @param mode 混合模式枚举值 */ void setBlendMode(BlendMode mode); /** * @brief 设置视图投影矩阵 * @param matrix 4x4视图投影矩阵 */ void setViewProjection(const glm::mat4 &matrix); /** * @brief 压入变换矩阵到变换栈 * @param transform 变换矩阵 */ void pushTransform(const glm::mat4 &transform); /** * @brief 从变换栈弹出顶部变换矩阵 */ void popTransform(); /** * @brief 获取当前累积的变换矩阵 * @return 当前变换矩阵,如果栈为空则返回单位矩阵 */ glm::mat4 getCurrentTransform() const; /** * @brief 创建纹理对象 * @param width 纹理宽度 * @param height 纹理高度 * @param pixels 像素数据指针 * @param channels 颜色通道数 * @return 创建的纹理智能指针 */ Ptr createTexture(int width, int height, const uint8_t *pixels, int channels); /** * @brief 从文件加载纹理 * @param filepath 纹理文件路径 * @return 加载的纹理智能指针 */ Ptr loadTexture(const std::string &filepath); /** * @brief 开始精灵批处理 */ void beginSpriteBatch(); /** * @brief 绘制精灵(带完整参数) * @param texture 纹理引用 * @param destRect 目标矩形(屏幕坐标) * @param srcRect 源矩形(纹理坐标) * @param tint 着色颜色 * @param rotation 旋转角度(度) * @param anchor 锚点位置(0-1范围) */ void drawSprite(const Texture &texture, const Rect &destRect, const Rect &srcRect, const Color &tint, float rotation, const Vec2 &anchor); /** * @brief 绘制精灵(简化版本) * @param texture 纹理引用 * @param position 绘制位置 * @param tint 着色颜色 */ void drawSprite(const Texture &texture, const Vec2 &position, const Color &tint); /** * @brief 结束精灵批处理并提交绘制 */ void endSpriteBatch(); /** * @brief 绘制线段 * @param start 起点坐标 * @param end 终点坐标 * @param color 线条颜色 * @param width 线条宽度 */ void drawLine(const Vec2 &start, const Vec2 &end, const Color &color, float width); /** * @brief 绘制矩形边框 * @param rect 矩形区域 * @param color 边框颜色 * @param width 线条宽度 */ void drawRect(const Rect &rect, const Color &color, float width); /** * @brief 填充矩形 * @param rect 矩形区域 * @param color 填充颜色 */ void fillRect(const Rect &rect, const Color &color); /** * @brief 绘制圆形边框 * @param center 圆心坐标 * @param radius 半径 * @param color 边框颜色 * @param segments 分段数 * @param width 线条宽度 */ void drawCircle(const Vec2 ¢er, float radius, const Color &color, int segments, float width); /** * @brief 填充圆形 * @param center 圆心坐标 * @param radius 半径 * @param color 填充颜色 * @param segments 分段数 */ void fillCircle(const Vec2 ¢er, float radius, const Color &color, int segments); /** * @brief 绘制三角形边框 * @param p1 第一个顶点 * @param p2 第二个顶点 * @param p3 第三个顶点 * @param color 边框颜色 * @param width 线条宽度 */ void drawTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3, const Color &color, float width); /** * @brief 填充三角形 * @param p1 第一个顶点 * @param p2 第二个顶点 * @param p3 第三个顶点 * @param color 填充颜色 */ void fillTriangle(const Vec2 &p1, const Vec2 &p2, const Vec2 &p3, const Color &color); /** * @brief 绘制多边形边框 * @param points 顶点数组 * @param color 边框颜色 * @param width 线条宽度 */ void drawPolygon(const std::vector &points, const Color &color, float width); /** * @brief 填充多边形 * @param points 顶点数组 * @param color 填充颜色 */ void fillPolygon(const std::vector &points, const Color &color); /** * @brief 绘制文本 * @param font 字体图集引用 * @param text 文本内容 * @param position 绘制位置 * @param color 文本颜色 */ void drawText(const FontAtlas &font, const std::string &text, const Vec2 &position, const Color &color); /** * @brief 绘制文本(使用浮点坐标) * @param font 字体图集引用 * @param text 文本内容 * @param x X坐标 * @param y Y坐标 * @param color 文本颜色 */ void drawText(const FontAtlas &font, const std::string &text, float x, float y, const Color &color); /** * @brief 获取渲染统计信息 * @return 渲染统计信息 */ RenderStats getStats() const { return stats_; } /** * @brief 重置渲染统计信息 */ void resetStats(); private: // 形状批处理常量 static constexpr size_t MAX_CIRCLE_SEGMENTS = 128; static constexpr size_t MAX_SHAPE_VERTICES = 8192; // 最大形状顶点数 static constexpr size_t MAX_LINE_VERTICES = 16384; // 最大线条顶点数 // 形状顶点结构(包含颜色) struct ShapeVertex { float x, y; float r, g, b, a; }; SDL_Window *window_; GLSpriteBatch spriteBatch_; Ptr shapeShader_; GLuint shapeVao_; GLuint shapeVbo_; GLuint lineVao_; // 线条专用 VAO GLuint lineVbo_; // 线条专用 VBO glm::mat4 viewProjection_; std::vector transformStack_; RenderStats stats_; bool vsync_; // 形状批处理缓冲区(预分配,避免每帧内存分配) std::array shapeVertexCache_; size_t shapeVertexCount_ = 0; GLenum currentShapeMode_ = GL_TRIANGLES; // 线条批处理缓冲区 std::array lineVertexCache_; size_t lineVertexCount_ = 0; float currentLineWidth_ = 1.0f; // OpenGL 状态缓存 BlendMode cachedBlendMode_ = BlendMode::None; bool blendEnabled_ = false; void initShapeRendering(); void flushShapeBatch(); void flushLineBatch(); void addShapeVertex(float x, float y, const Color &color); void addLineVertex(float x, float y, const Color &color); void submitShapeBatch(GLenum mode); }; } // namespace frostbite2D