140 lines
3.9 KiB
C++
140 lines
3.9 KiB
C++
#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
|