Frostbite2D/Fostbite2D/include/fostbite2D/render/opengl/gl_renderer.h

317 lines
8.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <fostbite2D/core/color.h>
#include <fostbite2D/core/math_types.h>
#include <fostbite2D/core/types.h>
#include <fostbite2D/render/font.h>
#include <fostbite2D/render/opengl/gl_sprite_batch.h>
#include <fostbite2D/render/shader/shader_interface.h>
#include <fostbite2D/render/texture.h>
#include <array>
#include <glad/glad.h>
#include <vector>
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<Texture> createTexture(int width, int height, const uint8_t *pixels,
int channels);
/**
* @brief 从文件加载纹理
* @param filepath 纹理文件路径
* @return 加载的纹理智能指针
*/
Ptr<Texture> 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 &center, float radius, const Color &color,
int segments, float width);
/**
* @brief 填充圆形
* @param center 圆心坐标
* @param radius 半径
* @param color 填充颜色
* @param segments 分段数
*/
void fillCircle(const Vec2 &center, 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<Vec2> &points, const Color &color,
float width);
/**
* @brief 填充多边形
* @param points 顶点数组
* @param color 填充颜色
*/
void fillPolygon(const std::vector<Vec2> &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<IShader> shapeShader_;
GLuint shapeVao_;
GLuint shapeVbo_;
GLuint lineVao_; // 线条专用 VAO
GLuint lineVbo_; // 线条专用 VBO
glm::mat4 viewProjection_;
std::vector<glm::mat4> transformStack_;
RenderStats stats_;
bool vsync_;
// 形状批处理缓冲区(预分配,避免每帧内存分配)
std::array<ShapeVertex, MAX_SHAPE_VERTICES> shapeVertexCache_;
size_t shapeVertexCount_ = 0;
GLenum currentShapeMode_ = GL_TRIANGLES;
// 线条批处理缓冲区
std::array<ShapeVertex, MAX_LINE_VERTICES> 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