Add particle rendering in vulkan

This commit is contained in:
Benau 2022-09-18 11:31:06 +08:00
parent 4d79ccdea5
commit f270b4acf8
5 changed files with 62 additions and 10 deletions

View File

@ -20,6 +20,7 @@
#include "mini_glm.hpp"
#include "IBillboardSceneNode.h"
#include "IParticleSystemSceneNode.h"
#include <algorithm>
#include <limits>
@ -94,6 +95,24 @@ ObjectData::ObjectData(irr::scene::IBillboardSceneNode* node, int material_id,
m_custom_vertex_color.setBlue((top.getBlue() + bottom.getBlue()) / 2);
} // ObjectData
// ============================================================================
ObjectData::ObjectData(const irr::scene::SParticle& particle, int material_id,
const irr::core::quaternion& rotation)
{
using namespace MiniGLM;
memcpy(&m_translation_x, &particle.pos, sizeof(float) * 3);
memcpy(m_rotation, &rotation, sizeof(irr::core::quaternion));
irr::core::vector3df scale(particle.size.Width / 2.0f,
particle.size.Height / 2.0f, 0);
memcpy(&m_scale_x, &scale, sizeof(irr::core::vector3df));
m_skinning_offset = 0;
m_material_id = material_id;
m_texture_trans[0] = 0.0f;
m_texture_trans[1] = 0.0f;
m_hue_change = 0.0f;
m_custom_vertex_color = particle.color;
} // ObjectData
// ----------------------------------------------------------------------------
GEVulkanDrawCall::GEVulkanDrawCall()
{
@ -181,7 +200,8 @@ void GEVulkanDrawCall::addNode(irr::scene::ISceneNode* node)
} // addNode
// ----------------------------------------------------------------------------
void GEVulkanDrawCall::addBillboardNode(irr::scene::IBillboardSceneNode* node)
void GEVulkanDrawCall::addBillboardNode(irr::scene::ISceneNode* node,
irr::scene::ESCENE_NODE_TYPE node_type)
{
irr::core::aabbox3df bb = node->getTransformedBoundingBox();
if (m_culling_tool->isCulled(bb))
@ -194,7 +214,9 @@ void GEVulkanDrawCall::addBillboardNode(irr::scene::IBillboardSceneNode* node)
m_billboard_buffers[textures] = new GEVulkanBillboardBuffer(m);
GESPMBuffer* buffer = m_billboard_buffers.at(textures);
const std::string& shader = getShader(node, 0);
m_visible_nodes[buffer][shader].emplace_back(node, BILLBOARD_NODE);
m_visible_nodes[buffer][shader].emplace_back(node,
node_type == irr::scene::ESNT_BILLBOARD ? BILLBOARD_NODE :
PARTICLE_NODE);
} // addBillboardNode
// ----------------------------------------------------------------------------
@ -278,7 +300,7 @@ void GEVulkanDrawCall::generate()
for (auto& r : q.second)
{
irr::scene::ISceneNode* node = r.first;
if (r.second == BILLBOARD_NODE)
if (r.second == BILLBOARD_NODE || r.second == PARTICLE_NODE)
{
if (GEVulkanFeatures::supportsDifferentTexturePerDraw())
{
@ -287,9 +309,27 @@ void GEVulkanDrawCall::generate()
const irr::video::ITexture** list = &textures[0];
material_id = m_texture_descriptor->getTextureID(list);
}
m_visible_objects.emplace_back(
static_cast<irr::scene::IBillboardSceneNode*>(
node), material_id, m_billboard_rotation);
if (r.second == BILLBOARD_NODE)
{
m_visible_objects.emplace_back(
static_cast<irr::scene::IBillboardSceneNode*>(
node), material_id, m_billboard_rotation);
}
else
{
irr::scene::IParticleSystemSceneNode* pn =
static_cast<irr::scene::IParticleSystemSceneNode*>(
node);
const core::array<SParticle>& particles =
pn->getParticles();
unsigned ps = particles.size();
visible_count += ps - 1;
for (unsigned i = 0; i < ps; i++)
{
m_visible_objects.emplace_back(particles[i],
material_id, m_billboard_rotation);
}
}
}
else
{

View File

@ -13,6 +13,7 @@
#include "matrix4.h"
#include "quaternion.h"
#include "ESceneNodeTypes.h"
#include "SColor.h"
#include "SMaterial.h"
@ -54,6 +55,9 @@ struct ObjectData
// ------------------------------------------------------------------------
ObjectData(irr::scene::IBillboardSceneNode* node, int material_id,
const irr::core::quaternion& rotation);
// ------------------------------------------------------------------------
ObjectData(const irr::scene::SParticle& particle, int material_id,
const irr::core::quaternion& rotation);
};
struct PipelineSettings
@ -90,6 +94,8 @@ private:
const int BILLBOARD_NODE = -1;
const int PARTICLE_NODE = -2;
std::map<TexturesList, GESPMBuffer*> m_billboard_buffers;
irr::core::quaternion m_billboard_rotation;
@ -171,7 +177,8 @@ public:
// ------------------------------------------------------------------------
void addNode(irr::scene::ISceneNode* node);
// ------------------------------------------------------------------------
void addBillboardNode(irr::scene::IBillboardSceneNode* node);
void addBillboardNode(irr::scene::ISceneNode* node,
irr::scene::ESCENE_NODE_TYPE node_type);
// ------------------------------------------------------------------------
void prepare(GEVulkanCameraSceneNode* cam);
// ------------------------------------------------------------------------

View File

@ -274,10 +274,10 @@ irr::u32 GEVulkanSceneManager::registerNodeForRendering(
return 1;
}
if (node->getType() == irr::scene::ESNT_BILLBOARD)
if (node->getType() == irr::scene::ESNT_BILLBOARD ||
node->getType() == irr::scene::ESNT_PARTICLE_SYSTEM)
{
m_draw_calls.at(cam)->addBillboardNode(
static_cast<irr::scene::IBillboardSceneNode*>(node));
m_draw_calls.at(cam)->addBillboardNode(node, node->getType());
return 1;
}

View File

@ -16,6 +16,7 @@
#include "IParticleFadeOutAffector.h"
#include "IParticleGravityAffector.h"
#include "IParticleRotationAffector.h"
#include "irrArray.h"
#include "dimension2d.h"
namespace irr
@ -502,6 +503,8 @@ public:
virtual IParticleRotationAffector* createRotationAffector(
const core::vector3df& speed = core::vector3df(5.0f,5.0f,5.0f),
const core::vector3df& pivotPoint = core::vector3df(0.0f,0.0f,0.0f) ) = 0;
virtual core::array<SParticle>& getParticles() = 0;
};
} // end namespace scene

View File

@ -214,6 +214,8 @@ public:
//! Returns type of the scene node
virtual ESCENE_NODE_TYPE getType() const { return ESNT_PARTICLE_SYSTEM; }
virtual core::array<SParticle>& getParticles() { return Particles; }
protected:
void reallocateBuffers();