2026-02-11 19:40:26 +08:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
2026-02-25 06:23:53 +08:00
|
|
|
|
#include <core/color.h>
|
|
|
|
|
|
#include <core/types.h>
|
2026-02-26 20:06:51 +08:00
|
|
|
|
#include <core/vec2.h>
|
2026-02-25 06:23:53 +08:00
|
|
|
|
#include <graphics/opengl/gl_shader.h>
|
|
|
|
|
|
#include <graphics/texture.h>
|
2026-02-11 19:40:26 +08:00
|
|
|
|
#include <glm/mat4x4.hpp>
|
|
|
|
|
|
#include <vector>
|
2026-02-11 22:30:57 +08:00
|
|
|
|
#include <array>
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
#include <glad/glad.h>
|
|
|
|
|
|
|
|
|
|
|
|
namespace extra2d {
|
|
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
2026-02-11 22:30:57 +08:00
|
|
|
|
// OpenGL 精灵批渲染器 - 优化版本
|
2026-02-11 19:40:26 +08:00
|
|
|
|
// ============================================================================
|
|
|
|
|
|
class GLSpriteBatch {
|
|
|
|
|
|
public:
|
|
|
|
|
|
static constexpr size_t MAX_SPRITES = 10000;
|
|
|
|
|
|
static constexpr size_t VERTICES_PER_SPRITE = 4;
|
|
|
|
|
|
static constexpr size_t INDICES_PER_SPRITE = 6;
|
2026-02-11 22:30:57 +08:00
|
|
|
|
static constexpr size_t MAX_VERTICES = MAX_SPRITES * VERTICES_PER_SPRITE;
|
|
|
|
|
|
static constexpr size_t MAX_INDICES = MAX_SPRITES * INDICES_PER_SPRITE;
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
struct Vertex {
|
|
|
|
|
|
glm::vec2 position;
|
|
|
|
|
|
glm::vec2 texCoord;
|
|
|
|
|
|
glm::vec4 color;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct SpriteData {
|
|
|
|
|
|
glm::vec2 position;
|
|
|
|
|
|
glm::vec2 size;
|
|
|
|
|
|
glm::vec2 texCoordMin;
|
|
|
|
|
|
glm::vec2 texCoordMax;
|
|
|
|
|
|
glm::vec4 color;
|
|
|
|
|
|
float rotation;
|
|
|
|
|
|
glm::vec2 anchor;
|
|
|
|
|
|
bool isSDF = false;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
GLSpriteBatch();
|
|
|
|
|
|
~GLSpriteBatch();
|
|
|
|
|
|
|
|
|
|
|
|
bool init();
|
|
|
|
|
|
void shutdown();
|
|
|
|
|
|
|
|
|
|
|
|
void begin(const glm::mat4 &viewProjection);
|
|
|
|
|
|
void draw(const Texture &texture, const SpriteData &data);
|
|
|
|
|
|
void end();
|
|
|
|
|
|
|
2026-02-11 22:30:57 +08:00
|
|
|
|
// 批量绘制接口 - 用于自动批处理
|
|
|
|
|
|
void drawBatch(const Texture& texture, const std::vector<SpriteData>& sprites);
|
|
|
|
|
|
|
|
|
|
|
|
// 立即绘制(不缓存)
|
|
|
|
|
|
void drawImmediate(const Texture& texture, const SpriteData& data);
|
|
|
|
|
|
|
2026-02-11 19:40:26 +08:00
|
|
|
|
// 统计
|
|
|
|
|
|
uint32_t getDrawCallCount() const { return drawCallCount_; }
|
|
|
|
|
|
uint32_t getSpriteCount() const { return spriteCount_; }
|
2026-02-11 22:30:57 +08:00
|
|
|
|
uint32_t getBatchCount() const { return batchCount_; }
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否需要刷新
|
|
|
|
|
|
bool needsFlush(const Texture& texture, bool isSDF) const;
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
GLuint vao_;
|
|
|
|
|
|
GLuint vbo_;
|
|
|
|
|
|
GLuint ibo_;
|
|
|
|
|
|
GLShader shader_;
|
|
|
|
|
|
|
2026-02-11 22:30:57 +08:00
|
|
|
|
// 使用固定大小数组减少内存分配
|
|
|
|
|
|
std::array<Vertex, MAX_VERTICES> vertexBuffer_;
|
|
|
|
|
|
size_t vertexCount_;
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
const Texture *currentTexture_;
|
|
|
|
|
|
bool currentIsSDF_;
|
|
|
|
|
|
glm::mat4 viewProjection_;
|
2026-02-13 10:43:38 +08:00
|
|
|
|
|
|
|
|
|
|
// 缓存上一帧的 viewProjection,避免重复设置
|
|
|
|
|
|
glm::mat4 cachedViewProjection_;
|
|
|
|
|
|
bool viewProjectionDirty_ = true;
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
uint32_t drawCallCount_;
|
|
|
|
|
|
uint32_t spriteCount_;
|
2026-02-11 22:30:57 +08:00
|
|
|
|
uint32_t batchCount_;
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
void flush();
|
|
|
|
|
|
void setupShader();
|
2026-02-11 22:30:57 +08:00
|
|
|
|
|
|
|
|
|
|
// 添加顶点到缓冲区
|
|
|
|
|
|
void addVertices(const SpriteData& data);
|
2026-02-11 19:40:26 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace extra2d
|