Extra2D/examples/scene_graph_demo/instanced_test.cpp

140 lines
3.9 KiB
C++
Raw Normal View History

#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