删除ECS模式

This commit is contained in:
2025-03-26 17:25:55 +08:00
parent 79363ce141
commit e44a9bda57
65 changed files with 1250 additions and 1841 deletions

View File

@@ -0,0 +1,307 @@
#include "render_elements.h"
#include "shaders/mirage_rounded_rect.hlsl.h"
template<typename Derived>
void compute_rect_vertices(const Eigen::MatrixBase<Derived>& in_pos,
const Eigen::MatrixBase<Derived>& in_size,
Eigen::Matrix<float, 2, 4>& positions,
float rotation_radians = 0.0f,
const Eigen::Vector2f& scale = Eigen::Vector2f(1.0f, 1.0f),
const Eigen::Vector2f& pivot = Eigen::Vector2f(0.5f, 0.5f)) {
// 计算缩放后的尺寸
Eigen::Array2f scaled_size = in_size.array() * scale.array();
// 计算旋转矩阵
const Eigen::Rotation2D<float> rotation(rotation_radians);
const Eigen::Matrix2f rot_matrix = rotation.toRotationMatrix();
// 计算基于原点的矩形顶点(左上角在原点)
Eigen::Matrix<float, 2, 4> rect_points;
rect_points.col(0) = Eigen::Vector2f(0, 0); // 左上
rect_points.col(1) = Eigen::Vector2f(scaled_size.x(), 0); // 右上
rect_points.col(2) = Eigen::Vector2f(0, scaled_size.y()); // 左下
rect_points.col(3) = Eigen::Vector2f(scaled_size.x(), scaled_size.y()); // 右下
// 计算锚点偏移(相对于左上角)
const auto& pivot_offset = Eigen::Vector2f(scaled_size.x() * pivot.x(),
scaled_size.y() * pivot.y());
// 应用旋转(绕锚点旋转)
for (int i = 0; i < 4; ++i) {
// 将点移到锚点为中心
Eigen::Vector2f centered = rect_points.col(i) - pivot_offset;
// 应用旋转
rect_points.col(i) = rot_matrix * centered + pivot_offset;
// 添加位置偏移
positions.col(i) = rect_points.col(i) + in_pos;
}
}
// 开始新一帧
void render_elements::begin_frame() {
vertices_.clear();
indices_.clear();
batches_.clear();
current_batch_index_ = -1;
current_key_ = batch_key{};
draw_call_count_ = 0;
total_triangles_ = 0;
}
// 设置渲染管线
void render_elements::set_pipeline(sg_pipeline pipeline) {
batch_key new_key = current_key_;
new_key.pipeline = pipeline;
ensure_batch_compatibility(new_key);
}
// 设置纹理
void render_elements::set_texture(sg_image image) {
batch_key new_key = current_key_;
new_key.image = image;
ensure_batch_compatibility(new_key);
}
Eigen::Matrix4f render_elements::create_projection_matrix(const Eigen::Vector2i& in_size) {
Eigen::Matrix4f projection_matrix = Eigen::Matrix4f::Identity();
// 缩放因子
const float scale_x = 2.0f / in_size.x();
const float scale_y = -2.0f / in_size.y(); // Y轴翻转因为窗口坐标系Y轴向下
// 平移因子
constexpr float translate_x = -1.0f;
constexpr float translate_y = 1.0f;
// 设置缩放
projection_matrix(0, 0) = scale_x;
projection_matrix(1, 1) = scale_y;
// 设置平移
projection_matrix(0, 3) = translate_x;
projection_matrix(1, 3) = translate_y;
return projection_matrix;
}
void render_elements::init_window_size(const Eigen::Vector2i& in_size) {
window_size_ = in_size;
projection_matrix_ = create_projection_matrix(in_size);
}
void render_elements::update_projection_matrix(const Eigen::Vector2i& in_size) {
window_size_ = in_size;
projection_matrix_ = create_projection_matrix(in_size);
}
// 确保批次兼容性
void render_elements::ensure_batch_compatibility(const batch_key& key) {
// 如果当前没有批次或者渲染状态改变了,创建新批次
if (current_batch_index_ < 0 || current_key_ != key) {
current_key_ = key;
draw_batch new_batch;
new_batch.key = key;
new_batch.vertex_start = vertices_.size();
new_batch.index_start = indices_.size();
batches_.push_back(new_batch);
current_batch_index_ = batches_.size() - 1;
}
}
// 添加矩形到当前批次
void render_elements::add_rect_to_batch(
const Eigen::Vector2f& in_pos,
const Eigen::Vector2f& in_size,
const rect_color& in_color,
const mirage_vertex_param_t& in_param_a,
const mirage_vertex_param_t& in_param_b,
const mirage_vertex_param_t& in_param_c,
const rect_uv& in_uv,
float in_rotation_radians,
const Eigen::Vector2f& in_pivot,
const Eigen::Vector2f& in_scale) {
// 确保有活跃的批次
if (current_batch_index_ < 0) {
set_pipeline(sg_pipeline{}); // 使用默认管线
set_texture(sg_image{}); // 使用默认纹理
}
// 计算顶点位置
Eigen::Matrix<float, 2, 4> positions;
compute_rect_vertices(in_pos, in_size, positions, in_rotation_radians, in_pivot, in_scale);
// 记录起始顶点索引
uint32_t base_index = vertices_.size();
// 添加顶点
for (int i = 0; i < 4; ++i) {
auto& vertex = vertices_.emplace_back();
vertex.position = positions.col(i);
vertex.color = in_color[i];
vertex.uv = in_uv[i];
vertex.param_a = in_param_a;
vertex.param_b = in_param_b;
vertex.param_c = in_param_c;
}
// 添加索引(两个三角形)
indices_.push_back(base_index);
indices_.push_back(base_index + 1);
indices_.push_back(base_index + 2);
indices_.push_back(base_index + 1);
indices_.push_back(base_index + 3);
indices_.push_back(base_index + 2);
// 更新当前批次的计数
draw_batch& batch = batches_[current_batch_index_];
batch.vertex_count = vertices_.size() - batch.vertex_start;
batch.index_count = indices_.size() - batch.index_start;
// 更新统计信息
total_triangles_ += 2;
}
// 创建矩形(公开接口)
void render_elements::make_rect(
const Eigen::Vector2f& in_pos,
const Eigen::Vector2f& in_size,
const rect_color& in_color,
const geometry_t& in_geometry,
const mirage_vertex_param_t& in_param_a,
const mirage_vertex_param_t& in_param_b,
const mirage_vertex_param_t& in_param_c,
const rect_uv& in_uv,
float in_rotation_radians,
const Eigen::Vector2f& in_pivot,
const Eigen::Vector2f& in_scale) {
const auto& pos = in_geometry.local_to_window(in_pos);
add_rect_to_batch(pos,
in_size,
in_color,
in_param_a,
in_param_b,
in_param_c,
in_uv,
in_rotation_radians,
in_pivot,
in_scale);
}
void render_elements::make_rounded_rect(const Eigen::Vector2f& in_pos, const Eigen::Vector2f& in_size,
const geometry_t& in_geometry, const rect_color& in_color, const rect_round& in_round, float in_rotation_radians,
const Eigen::Vector2f& in_pivot, const rect_uv& in_uv, const Eigen::Vector2f& in_scale) {
set_pipeline(rounded_rect_pipeline_);
const mirage_vertex_param_t param_a{ in_size };
const mirage_vertex_param_t param_b{ in_round };
make_rect(in_pos, in_size, in_color, in_geometry, param_a, param_b, {}, in_uv, in_rotation_radians, in_scale, in_pivot);
}
// 确保缓冲区容量
void render_elements::ensure_buffer_capacity(uint32_t vertex_count, uint32_t index_count) {
// 如果现有缓冲区不够大,重新创建
if (vertex_count > vertex_buffer_capacity_) {
// 销毁旧缓冲区
if (vertex_buffer_.id != SG_INVALID_ID) { sg_destroy_buffer(vertex_buffer_); }
// 创建新缓冲区,容量翻倍以减少重新分配
vertex_buffer_capacity_ = vertex_count * 2;
sg_buffer_desc vbuf_desc = {};
vbuf_desc.size = vertex_buffer_capacity_ * sizeof(mirage_vertex_t);
vbuf_desc.usage = SG_USAGE_STREAM;
vertex_buffer_ = sg_make_buffer(&vbuf_desc);
}
if (index_count > index_buffer_capacity_) {
if (index_buffer_.id != SG_INVALID_ID) { sg_destroy_buffer(index_buffer_); }
index_buffer_capacity_ = index_count * 2;
sg_buffer_desc ibuf_desc = {};
ibuf_desc.size = index_buffer_capacity_ * sizeof(uint32_t);
ibuf_desc.usage = SG_USAGE_STREAM;
ibuf_desc.type = SG_BUFFERTYPE_INDEXBUFFER;
index_buffer_ = sg_make_buffer(&ibuf_desc);
}
}
// 上传并绘制所有批次
void render_elements::flush_batches() {
// 如果没有数据,直接返回
if (vertices_.empty() || indices_.empty() || batches_.empty()) { return; }
// 确保缓冲区足够大
ensure_buffer_capacity(vertices_.size(), indices_.size());
// 上传顶点和索引数据
sg_update_buffer(vertex_buffer_, sg_range{ vertices_.data(), vertices_.size() * sizeof(mirage_vertex_t) });
sg_update_buffer(index_buffer_, sg_range{ indices_.data(), indices_.size() * sizeof(uint32_t) });
// 绑定顶点和索引缓冲区
sg_bindings bind = {};
bind.vertex_buffers[0] = vertex_buffer_;
bind.index_buffer = index_buffer_;
// 渲染每个批次
for (const auto& batch: batches_) {
// 设置纹理
bind.images[0] = batch.key.image;
// 绑定管线
sg_apply_pipeline(batch.key.pipeline);
sg_apply_bindings(&bind);
sg_apply_uniforms(0, SG_RANGE(projection_matrix_));
// 绘制批次
sg_draw(batch.index_start, batch.index_count, 1);
draw_call_count_++;
}
}
// 结束帧并提交所有批次
void render_elements::end_frame() { flush_batches(); }
// 析构函数
render_elements::~render_elements() {
if (!sg_isvalid())
return;
if (vertex_buffer_.id != SG_INVALID_ID) { sg_destroy_buffer(vertex_buffer_); }
if (index_buffer_.id != SG_INVALID_ID) { sg_destroy_buffer(index_buffer_); }
}
void render_elements::create_resources() {
constexpr uint32_t default_vertex_buffer_size = 512; // 512kb
constexpr uint32_t default_index_buffer_size = 256; // 256kb
// 计算默认顶点, 使用default_vertex_buffer_size对齐到sizeof(mirage_vertex_t)
vertex_buffer_capacity_ = default_vertex_buffer_size * 1024 / sizeof(mirage_vertex_t);
index_buffer_capacity_ = default_index_buffer_size * 1024 / sizeof(uint32_t);
// 创建顶点缓冲区
sg_buffer_desc vbuf_desc = {};
vbuf_desc.size = vertex_buffer_capacity_ * sizeof(mirage_vertex_t);
vbuf_desc.usage = SG_USAGE_STREAM;
vbuf_desc.type = SG_BUFFERTYPE_VERTEXBUFFER;
vertex_buffer_ = sg_make_buffer(&vbuf_desc);
// 创建索引缓冲区
sg_buffer_desc ibuf_desc = {};
ibuf_desc.size = index_buffer_capacity_ * sizeof(mirage_triangle_t);
ibuf_desc.usage = SG_USAGE_STREAM;
ibuf_desc.type = SG_BUFFERTYPE_INDEXBUFFER;
index_buffer_ = sg_make_buffer(&ibuf_desc);
}
void render_elements::load_mirage_pipelines() {
#if MIRAGE_USE_HDR
auto format = MIRAGE_HDR_FORMAT;
#else
auto format = MIRAGE_PIXEL_FORMAT;
#endif
auto rounded_rect_shader = sg_make_shader(get_mirage_rounded_rect_shader_desc());
auto rounded_rect_pipeline_desc = get_mirage_rounded_rect_pipeline_desc(rounded_rect_shader,
format,
1);
rounded_rect_pipeline_ = sg_make_pipeline(rounded_rect_pipeline_desc);
}