diff --git a/include/renderer/command_queue.h b/include/renderer/command_queue.h index 8d783b1..f49881a 100644 --- a/include/renderer/command_queue.h +++ b/include/renderer/command_queue.h @@ -411,9 +411,8 @@ private: * @brief 执行单个批次 * @param batchIndex 批次索引 * @param batch 命令批次 - * @param frameIndex 当前帧索引(用于双缓冲) */ - void executeBatch(uint32_t batchIndex, const CommandBatch &batch, uint32_t frameIndex); + void executeBatch(uint32_t batchIndex, const CommandBatch &batch); /** * @brief 分配材质 UBO 空间(使用 CPU 缓冲区) diff --git a/include/renderer/render_types.h b/include/renderer/render_types.h index 6063772..f4111da 100644 --- a/include/renderer/render_types.h +++ b/include/renderer/render_types.h @@ -102,6 +102,28 @@ struct RenderCommand { Color getColor() const { return drawMesh.color; } }; +constexpr uint32_t SORT_KEY_LAYER_SHIFT = 24; +constexpr uint32_t SORT_KEY_DEPTH_SHIFT = 8; +constexpr uint32_t SORT_KEY_LAYER_MASK = 0xFF; +constexpr uint32_t SORT_KEY_DEPTH_MASK = 0xFFFF; +constexpr uint32_t SORT_KEY_FLAGS_MASK = 0xFF; + +inline uint32_t makeSortKey(uint8_t layer, uint16_t depth, uint8_t flags = 0) { + return (static_cast(layer) << SORT_KEY_LAYER_SHIFT) | + (static_cast(depth) << SORT_KEY_DEPTH_SHIFT) | + static_cast(flags); +} + +inline uint8_t extractSortLayer(uint32_t sortKey) { + return static_cast((sortKey >> SORT_KEY_LAYER_SHIFT) & + SORT_KEY_LAYER_MASK); +} + +inline uint16_t extractSortDepth(uint32_t sortKey) { + return static_cast((sortKey >> SORT_KEY_DEPTH_SHIFT) & + SORT_KEY_DEPTH_MASK); +} + // 清除标志 constexpr uint32_t CLEAR_COLOR_FLAG = 1 << 0; constexpr uint32_t CLEAR_DEPTH_FLAG = 1 << 1; diff --git a/include/scene/components/transform_component.h b/include/scene/components/transform_component.h index c7814a4..a5b35e1 100644 --- a/include/scene/components/transform_component.h +++ b/include/scene/components/transform_component.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -150,6 +151,7 @@ public: * @return 是否脏 */ bool isDirty() const { return dirty_; } + uint64_t getWorldVersion() const; private: /** @@ -160,6 +162,10 @@ private: Transform local_; mutable Transform world_; mutable bool dirty_ = true; + uint64_t localVersion_ = 1; + mutable uint64_t cachedLocalVersion_ = 0; + mutable uint64_t cachedParentVersion_ = 0; + mutable uint64_t worldVersion_ = 0; Vec2 anchor_ = Vec2(0.5f, 0.5f); Vec2 size_ = Vec2(100.0f, 100.0f); }; diff --git a/src/renderer/command_queue.cpp b/src/renderer/command_queue.cpp index 703d5ad..8b1e266 100644 --- a/src/renderer/command_queue.cpp +++ b/src/renderer/command_queue.cpp @@ -366,8 +366,8 @@ void CommandQueue::submitDraw(Ptr material, Ptr mesh, // 构建排序键 uint32_t materialId = getMaterialId(material.get()); - uint16_t depth = static_cast((sortKey >> 8) & 0xFFFF); - uint8_t layer = static_cast(sortKey & 0xFF); + uint16_t depth = extractSortDepth(sortKey); + uint8_t layer = extractSortLayer(sortKey); cmd.key = DrawKey::make(materialId, depth, layer); // 设置管线 @@ -500,8 +500,16 @@ void CommandQueue::execute(uint32_t frameIndex) { // 执行批次 const auto executeStart = Clock::now(); + if (uboManager_) { + UniformBuffer *globalUBO = uboManager_->getGlobalUBO(frameIndex); + if (globalUBO) { + commandList_->setUniformBuffer(0, globalUBO->getRHIBuffer()); + stats_.bufferBinds++; + } + } + for (uint32_t i = 0; i < batcher_.getBatchCount(); ++i) { - executeBatch(i, batcher_.getBatch(i), frameIndex); + executeBatch(i, batcher_.getBatch(i)); } // 提交命令到 GPU @@ -521,8 +529,7 @@ void CommandQueue::execute(uint32_t frameIndex) { std::chrono::duration(executeEnd - totalStart).count(); } -void CommandQueue::executeBatch(uint32_t batchIndex, const CommandBatch &batch, - uint32_t frameIndex) { +void CommandQueue::executeBatch(uint32_t batchIndex, const CommandBatch &batch) { if (!commandList_) { return; } @@ -535,15 +542,6 @@ void CommandQueue::executeBatch(uint32_t batchIndex, const CommandBatch &batch, E2D_WARN("批次没有有效的管线!"); } - // 绑定全局 UBO (binding = 0) - 使用双缓冲 - if (uboManager_) { - UniformBuffer *globalUBO = uboManager_->getGlobalUBO(frameIndex); - if (globalUBO) { - commandList_->setUniformBuffer(0, globalUBO->getRHIBuffer()); - stats_.bufferBinds++; - } - } - // 绑定纹理 if (batch.textureCount > 0) { for (uint32_t i = 0; i < batch.textureCount; ++i) { diff --git a/src/scene/components/sprite_renderer.cpp b/src/scene/components/sprite_renderer.cpp index 6b37f13..48e6c87 100644 --- a/src/scene/components/sprite_renderer.cpp +++ b/src/scene/components/sprite_renderer.cpp @@ -29,9 +29,9 @@ void SpriteRenderer::render() { RenderCommand cmd; cmd.type = RenderCommandType::DrawMesh; - uint32_t materialId = material_.index(); - uint32_t textureId = texture_.index(); - cmd.sortKey = (materialId << 16) | (textureId & 0xFFFF); + int32 layerTag = owner_->getTag(); + uint8_t layer = layerTag < 0 ? 0 : static_cast(layerTag & 0xFF); + cmd.sortKey = makeSortKey(layer, 0); // 如果没有指定网格,使用默认的四边形网格 cmd.drawMesh.mesh = Handle::invalid(); // RendererModule 会使用默认网格 diff --git a/src/scene/components/transform_component.cpp b/src/scene/components/transform_component.cpp index ce13ae4..37ea19c 100644 --- a/src/scene/components/transform_component.cpp +++ b/src/scene/components/transform_component.cpp @@ -70,14 +70,7 @@ Vec2 TransformComponent::getAnchorOffset() const { void TransformComponent::setDirty() { dirty_ = true; - // 递归标记所有子节点为脏 - if (owner_) { - for (auto& child : owner_->getChildren()) { - if (auto* transform = child->getTransform()) { - transform->setDirty(); - } - } - } + ++localVersion_; } /** @@ -87,7 +80,18 @@ void TransformComponent::setDirty() { * 默认1x1的四边形配合64x64的尺寸会正确显示为64x64像素大小。 */ void TransformComponent::updateWorldTransform() const { - if (!dirty_) return; + uint64_t parentVersion = 0; + Transform parentWorld; + if (owner_ && owner_->getParent()) { + if (auto* parentTransform = owner_->getParent()->getTransform()) { + parentWorld = parentTransform->getWorldTransform(); + parentVersion = parentTransform->getWorldVersion(); + } + } + if (!dirty_ && cachedLocalVersion_ == localVersion_ && + cachedParentVersion_ == parentVersion) { + return; + } // 计算本地旋转(度数转弧度) float rotRad = local_.rot * glm::pi() / 180.0f; @@ -100,8 +104,6 @@ void TransformComponent::updateWorldTransform() const { // 计算世界变换 if (owner_ && owner_->getParent()) { // 有父节点,需要组合变换 - Transform parentWorld = owner_->getParent()->getWorldTransform(); - // 本地旋转后的锚点偏移 float rotatedOffsetX = anchorOffset.x * c - anchorOffset.y * s; float rotatedOffsetY = anchorOffset.x * s + anchorOffset.y * c; @@ -135,6 +137,9 @@ void TransformComponent::updateWorldTransform() const { } dirty_ = false; + cachedLocalVersion_ = localVersion_; + cachedParentVersion_ = parentVersion; + ++worldVersion_; } Transform TransformComponent::getWorldTransform() const { @@ -142,6 +147,11 @@ Transform TransformComponent::getWorldTransform() const { return world_; } +uint64_t TransformComponent::getWorldVersion() const { + updateWorldTransform(); + return worldVersion_; +} + Mat4 TransformComponent::getWorldMatrix() const { updateWorldTransform(); diff --git a/src/scene/node.cpp b/src/scene/node.cpp index 6a07ebd..f216b1e 100644 --- a/src/scene/node.cpp +++ b/src/scene/node.cpp @@ -175,14 +175,12 @@ void Node::onExit() { } void Node::update(float dt) { - // 更新所有组件 for (auto& comp : components_) { - if (comp->isEnabled()) { + if (comp.get() != transform_ && comp->isEnabled()) { comp->update(dt); } } - // 递归更新子节点 for (auto& child : children_) { child->update(dt); } @@ -191,14 +189,16 @@ void Node::update(float dt) { void Node::render() { if (!visible_) return; - // 渲染所有组件 + if (children_.empty() && components_.size() == 1) { + return; + } + for (auto& comp : components_) { - if (comp->isEnabled()) { + if (comp.get() != transform_ && comp->isEnabled()) { comp->render(); } } - // 递归渲染子节点 for (auto& child : children_) { child->render(); }