You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中如何将SpriteComponent的Display调用重定向到LayerComponent的Display

问题根因说明

你当前只显示一半内容的核心问题出在LayerComponent::Display的实现逻辑上:当前代码只读取了精灵列表中第一个精灵的资源、只执行了一次绘制调用,剩余精灵完全没有参与渲染。

修复方案

第一步:修复LayerComponent渲染逻辑

先调整Layer的绘制逻辑,实现批量渲染:

  • 先对当前图层下的所有精灵按所属SpriteSheet分组,不同图集的精灵拆分到不同渲染批次
  • 每个批次合并所有精灵的顶点、索引数据到共享缓冲区,绑定一次图集后执行一次绘制,传入当前批次的总索引数
    调整后的代码示例:
void LayerComponent::Display(const Timing& timing)
{
    auto layerSprites = ListSprites(Owner().shared_from_this());
    if (layerSprites.empty())
    {
      return;
    }

    // 按SpriteSheet分组,此处简化处理假设同图层所有精灵共用同一个图集
    auto spriteSheet = gsl::at(layerSprites, 0)->GetSpriteSheet();
    Ensures(spriteSheet.Ready());
    
    // 合并所有精灵的顶点、索引
    std::vector<Vertex> totalVertices;
    std::vector<uint16_t> totalIndices;
    for (const auto& sprite : layerSprites) {
        // 累加顶点数据
        auto vertices = sprite->GetVertices();
        totalVertices.insert(totalVertices.end(), vertices.begin(), vertices.end());
        // 索引叠加当前顶点偏移量,避免绘制错乱
        auto indices = sprite->GetIndices();
        uint16_t baseVertex = static_cast<uint16_t>(totalVertices.size() - vertices.size());
        for (auto idx : indices) {
            totalIndices.push_back(idx + baseVertex);
        }
    }

    // 一次性绑定缓冲区+绘制
    spriteSheet->Bind(CreateVertexBuffer(totalVertices), CreateIndexBuffer(totalIndices));
    glDrawElements(GL_TRIANGLES, (GLsizei)totalIndices.size(), GL_UNSIGNED_SHORT, nullptr);
    spriteSheet->Unbind();
}

注:缓冲区创建可优化为复用固定大小的预分配缓冲区,避免每帧申请释放内存产生额外开销

第二步:重定向SpriteComponent::Display调用,解决编译错误

不需要删除SpriteComponent::Display函数,直接修改其实现即可兼容原有所有调用:

方案A(推荐,无额外开销)

直接置空实现,所有渲染逻辑完全交给Layer统一处理,上层原有调用完全不需要修改,不会产生编译错误:

void SpriteComponent::Display(const Timing& timing)
{
    // 渲染逻辑已迁移到所属LayerComponent批量处理,此处留空兼容原有调用
}

如果你的渲染逻辑是遍历所有VisualComponent子类触发Display,可以额外调整组件注册逻辑,将SpriteComponent从渲染遍历列表中移除,仅保留LayerComponent的遍历,进一步减少空函数调用开销。

方案B(兼容单独渲染场景)

如果部分场景需要单个Sprite单独渲染,可改为转发到所属Layer的Display,注意加帧内绘制标记避免重复渲染:

void SpriteComponent::Display(const Timing& timing)
{
    if (auto layer = GetOwningLayer().lock()) {
        layer->Display(timing);
    }
}

内容的提问来源于stack exchange,提问作者S3yll

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 21:39:02