Extra2D/examples/scene_graph_demo/instanced_test.cpp

140 lines
3.9 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.

#include "instanced_test.h"
#include <assets/assets_module.h>
#include <event/events.h>
#include <module/module_registry.h>
#include <renderer/renderer_module.h>
#include <utils/logger.h>
#include <cmath>
namespace extra2d {
InstancedTestNode::InstancedTestNode() {
setName("InstancedTest");
}
InstancedTestNode::~InstancedTestNode() {
instanceBuffer_.shutdown();
}
bool InstancedTestNode::initialize(uint32_t instanceCount) {
instanceCount_ = instanceCount;
// 获取资源模块
auto* assets = getModule<AssetsModule>();
if (!assets) {
E2D_LOG_ERROR("InstancedTestNode: AssetsModule not available");
return false;
}
// 使用默认网格(四边形)
mesh_ = assets->getDefaultQuad();
if (!mesh_.isValid()) {
E2D_LOG_ERROR("InstancedTestNode: Failed to get default quad mesh");
return false;
}
// 使用默认纹理
texture_ = assets->getDefaultTexture();
// 获取实例化渲染材质
material_ = assets->getInstancedMaterial();
if (!material_.isValid()) {
E2D_LOG_ERROR("InstancedTestNode: Failed to get instanced material");
return false;
}
// 初始化实例缓冲区
if (!instanceBuffer_.initialize(instanceCount)) {
E2D_LOG_ERROR("InstancedTestNode: Failed to initialize instance buffer");
return false;
}
// 预分配实例数据
instanceData_.resize(instanceCount);
// 初始化实例数据
updateInstances();
E2D_LOG_INFO("InstancedTestNode initialized with {} instances", instanceCount);
return true;
}
void InstancedTestNode::update(float dt) {
time_ += dt;
// 更新实例变换
updateInstances();
// 更新GPU缓冲区
if (!instanceData_.empty()) {
instanceBuffer_.updateInstances(instanceData_.data(), instanceCount_);
}
}
void InstancedTestNode::updateInstances() {
// 创建螺旋分布的实例
float radius = 200.0f;
float centerX = 640.0f;
float centerY = 360.0f;
for (uint32_t i = 0; i < instanceCount_; ++i) {
float t = static_cast<float>(i) / instanceCount_;
float angle = t * 6.28318f * 3.0f + time_; // 3圈螺旋
float r = radius * (0.2f + 0.8f * t);
// 位置
instanceData_[i].position.x = centerX + r * std::cos(angle);
instanceData_[i].position.y = centerY + r * std::sin(angle);
// 旋转(朝向中心)
instanceData_[i].rotation = angle + 1.5708f;
// 缩放(随距离变化)
float scale = 0.5f + 0.5f * t;
instanceData_[i].scale.x = scale * 32.0f;
instanceData_[i].scale.y = scale * 32.0f;
// 颜色(彩虹色)
float hue = t + time_ * 0.1f;
float r_color = std::abs(std::fmod(hue * 6.0f, 2.0f) - 1.0f);
float g_color = std::abs(std::fmod(hue * 6.0f + 2.0f, 2.0f) - 1.0f);
float b_color = std::abs(std::fmod(hue * 6.0f + 4.0f, 2.0f) - 1.0f);
instanceData_[i].color.r = r_color;
instanceData_[i].color.g = g_color;
instanceData_[i].color.b = b_color;
instanceData_[i].color.a = 1.0f;
// UV坐标使用完整纹理
instanceData_[i].uvX = 0.0f;
instanceData_[i].uvY = 0.0f;
instanceData_[i].uvWidth = 1.0f;
instanceData_[i].uvHeight = 1.0f;
}
}
void InstancedTestNode::render() {
if (!isVisible() || instanceCount_ == 0) {
return;
}
// 检查资源有效性
if (!mesh_.isValid() || !material_.isValid() || !instanceBuffer_.isValid()) {
return;
}
// 提交实例化渲染命令
RenderCommand cmd;
cmd.type = RenderCommandType::DrawMeshInstanced;
cmd.sortKey = 0;
cmd.drawInstanced.mesh = mesh_;
cmd.drawInstanced.material = material_;
cmd.drawInstanced.instanceBuffer = &instanceBuffer_;
cmd.drawInstanced.instanceCount = instanceCount_;
cmd.drawInstanced.instanceOffset = 0;
events::OnRenderSubmit::emit(cmd);
}
} // namespace extra2d