Add flips particle rendering for vulkan
This commit is contained in:
parent
46f44b5d59
commit
1fc460ff4e
@ -23,8 +23,12 @@
|
|||||||
#include "IParticleSystemSceneNode.h"
|
#include "IParticleSystemSceneNode.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
#include "../source/Irrlicht/os.h"
|
||||||
|
#include "quaternion.h"
|
||||||
|
|
||||||
namespace GE
|
namespace GE
|
||||||
{
|
{
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@ -71,11 +75,11 @@ void ObjectData::init(irr::scene::ISceneNode* node, int material_id,
|
|||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
void ObjectData::init(irr::scene::IBillboardSceneNode* node, int material_id,
|
void ObjectData::init(irr::scene::IBillboardSceneNode* node, int material_id,
|
||||||
const irr::core::quaternion& rotation)
|
const btQuaternion& rotation)
|
||||||
{
|
{
|
||||||
memcpy(&m_translation_x, &node->getAbsoluteTransformation()[12],
|
memcpy(&m_translation_x, &node->getAbsoluteTransformation()[12],
|
||||||
sizeof(float) * 3);
|
sizeof(float) * 3);
|
||||||
memcpy(m_rotation, &rotation, sizeof(irr::core::quaternion));
|
memcpy(m_rotation, &rotation[0], sizeof(btQuaternion));
|
||||||
irr::core::vector2df billboard_size = node->getSize();
|
irr::core::vector2df billboard_size = node->getSize();
|
||||||
m_scale_x = billboard_size.X / 2.0f;
|
m_scale_x = billboard_size.X / 2.0f;
|
||||||
m_scale_y = billboard_size.Y / 2.0f;
|
m_scale_y = billboard_size.Y / 2.0f;
|
||||||
@ -95,13 +99,62 @@ void ObjectData::init(irr::scene::IBillboardSceneNode* node, int material_id,
|
|||||||
m_custom_vertex_color = output;
|
m_custom_vertex_color = output;
|
||||||
} // init
|
} // init
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
std::vector<float> g_flips_data;
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
void ObjectData::init(const irr::scene::SParticle& particle, int material_id,
|
void ObjectData::init(const irr::scene::SParticle& particle, int material_id,
|
||||||
const irr::core::quaternion& rotation)
|
const btQuaternion& rotation,
|
||||||
|
const irr::core::vector3df& view_position, bool flips,
|
||||||
|
bool backface_culling)
|
||||||
{
|
{
|
||||||
memcpy(&m_translation_x, &particle.pos, sizeof(float) * 3);
|
memcpy(&m_translation_x, &particle.pos, sizeof(float) * 3);
|
||||||
memcpy(m_rotation, &rotation, sizeof(irr::core::quaternion));
|
float scale_x = particle.size.Width / 2.0f;
|
||||||
m_scale_x = particle.size.Width / 2.0f;
|
if (flips)
|
||||||
|
{
|
||||||
|
// Following stk_particle.cpp
|
||||||
|
const unsigned particle_index = particle.startTime;
|
||||||
|
const float lifetime = particle.startSize.Width;
|
||||||
|
const float pi = 3.14159265358979323846f;
|
||||||
|
while (particle_index + 1 > g_flips_data.size())
|
||||||
|
{
|
||||||
|
// Maximum 3 rotation around axis (0, 1, 0) during lifetime
|
||||||
|
g_flips_data.push_back(pi * 2.0f * 3.0f * os::Randomizer::frand() *
|
||||||
|
(g_flips_data.size() % 2 == 0 ? 1.0f : -1.0f));
|
||||||
|
}
|
||||||
|
float angle = fmodf(lifetime * g_flips_data[particle_index],
|
||||||
|
pi * 2.0f);
|
||||||
|
btQuaternion rotated(btVector3(0.0f, 1.0f, 0.0f), angle);
|
||||||
|
rotated = btQuaternion(rotation[0], rotation[1], rotation[2],
|
||||||
|
-rotation[3]) * rotated;
|
||||||
|
rotated.normalize();
|
||||||
|
// Conjugated quaternion in glsl
|
||||||
|
rotated[3] = -rotated[3];
|
||||||
|
memcpy(m_rotation, &rotated[0], sizeof(btQuaternion));
|
||||||
|
if (backface_culling)
|
||||||
|
{
|
||||||
|
irr::core::quaternion q(rotated[0], rotated[1], rotated[2],
|
||||||
|
-rotated[3]);
|
||||||
|
irr::core::matrix4 m;
|
||||||
|
q.getMatrix(m, particle.pos);
|
||||||
|
irr::core::vector3df tri[3] =
|
||||||
|
{
|
||||||
|
irr::core::vector3df( 1.0f, -1.0f, 0.0f),
|
||||||
|
irr::core::vector3df( 1.0f, 1.0f, 0.0f),
|
||||||
|
irr::core::vector3df(-1.0f, 1.0f, 0.0f)
|
||||||
|
};
|
||||||
|
m.transformVect(tri[0]);
|
||||||
|
m.transformVect(tri[1]);
|
||||||
|
m.transformVect(tri[2]);
|
||||||
|
irr::core::vector3df normal = (tri[1] - tri[0])
|
||||||
|
.crossProduct(tri[2] - tri[0]);
|
||||||
|
float dot_product = (tri[0] - view_position).dotProduct(normal);
|
||||||
|
if (dot_product < 0.0f)
|
||||||
|
scale_x = -scale_x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memcpy(m_rotation, &rotation[0], sizeof(btQuaternion));
|
||||||
|
m_scale_x = scale_x;
|
||||||
m_scale_y = particle.size.Height / 2.0f;
|
m_scale_y = particle.size.Height / 2.0f;
|
||||||
m_scale_z = 0.0f;
|
m_scale_z = 0.0f;
|
||||||
m_skinning_offset = 0;
|
m_skinning_offset = 0;
|
||||||
@ -400,6 +453,8 @@ start:
|
|||||||
k.m_hue_change == key.m_hue_change;
|
k.m_hue_change == key.m_hue_change;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const PipelineSettings& settings =
|
||||||
|
m_graphics_pipelines[cur_shader].second;
|
||||||
for (auto& r : q.second)
|
for (auto& r : q.second)
|
||||||
{
|
{
|
||||||
irr::scene::ISceneNode* node = r.first;
|
irr::scene::ISceneNode* node = r.first;
|
||||||
@ -449,10 +504,12 @@ start:
|
|||||||
goto start;
|
goto start;
|
||||||
}
|
}
|
||||||
ObjectData* obj = (ObjectData*)mapped_addr;
|
ObjectData* obj = (ObjectData*)mapped_addr;
|
||||||
|
bool flips = pn->getFlips();
|
||||||
for (unsigned i = 0; i < ps; i++)
|
for (unsigned i = 0; i < ps; i++)
|
||||||
{
|
{
|
||||||
obj[i].init(particles[i], material_id,
|
obj[i].init(particles[i], material_id,
|
||||||
m_billboard_rotation);
|
m_billboard_rotation, m_view_position, flips,
|
||||||
|
settings.m_backface_culling);
|
||||||
written_size += sizeof(ObjectData);
|
written_size += sizeof(ObjectData);
|
||||||
mapped_addr += sizeof(ObjectData);
|
mapped_addr += sizeof(ObjectData);
|
||||||
}
|
}
|
||||||
@ -507,8 +564,6 @@ start:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
cmd.firstInstance = it->m_first_instance;
|
cmd.firstInstance = it->m_first_instance;
|
||||||
const PipelineSettings& settings =
|
|
||||||
m_graphics_pipelines[cur_shader].second;
|
|
||||||
std::string sorting_key =
|
std::string sorting_key =
|
||||||
std::string(1, settings.m_drawing_priority) + cur_shader;
|
std::string(1, settings.m_drawing_priority) + cur_shader;
|
||||||
m_cmds.push_back({ cmd, cur_shader, sorting_key, p.first,
|
m_cmds.push_back({ cmd, cur_shader, sorting_key, p.first,
|
||||||
@ -699,7 +754,8 @@ void GEVulkanDrawCall::prepare(GEVulkanCameraSceneNode* cam)
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
m_culling_tool->init(cam);
|
m_culling_tool->init(cam);
|
||||||
m_billboard_rotation = MiniGLM::getQuaternion(cam->getViewMatrix());
|
m_view_position = cam->getPosition();
|
||||||
|
m_billboard_rotation = MiniGLM::getBulletQuaternion(cam->getViewMatrix());
|
||||||
} // prepare
|
} // prepare
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -12,11 +12,13 @@
|
|||||||
#include "vulkan_wrapper.h"
|
#include "vulkan_wrapper.h"
|
||||||
|
|
||||||
#include "matrix4.h"
|
#include "matrix4.h"
|
||||||
#include "quaternion.h"
|
#include "vector3d.h"
|
||||||
#include "ESceneNodeTypes.h"
|
#include "ESceneNodeTypes.h"
|
||||||
#include "SColor.h"
|
#include "SColor.h"
|
||||||
#include "SMaterial.h"
|
#include "SMaterial.h"
|
||||||
|
|
||||||
|
#include "LinearMath/btQuaternion.h"
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
namespace scene
|
namespace scene
|
||||||
@ -55,10 +57,12 @@ struct ObjectData
|
|||||||
int skinning_offset, int irrlicht_material_id);
|
int skinning_offset, int irrlicht_material_id);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void init(irr::scene::IBillboardSceneNode* node, int material_id,
|
void init(irr::scene::IBillboardSceneNode* node, int material_id,
|
||||||
const irr::core::quaternion& rotation);
|
const btQuaternion& rotation);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void init(const irr::scene::SParticle& particle, int material_id,
|
void init(const irr::scene::SParticle& particle, int material_id,
|
||||||
const irr::core::quaternion& rotation);
|
const btQuaternion& rotation,
|
||||||
|
const irr::core::vector3df& view_position, bool flips,
|
||||||
|
bool backface_culling);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PipelineSettings
|
struct PipelineSettings
|
||||||
@ -100,7 +104,9 @@ private:
|
|||||||
|
|
||||||
std::map<TexturesList, GESPMBuffer*> m_billboard_buffers;
|
std::map<TexturesList, GESPMBuffer*> m_billboard_buffers;
|
||||||
|
|
||||||
irr::core::quaternion m_billboard_rotation;
|
irr::core::vector3df m_view_position;
|
||||||
|
|
||||||
|
btQuaternion m_billboard_rotation;
|
||||||
|
|
||||||
std::unordered_map<GESPMBuffer*, std::unordered_map<std::string,
|
std::unordered_map<GESPMBuffer*, std::unordered_map<std::string,
|
||||||
std::vector<std::pair<irr::scene::ISceneNode*, int> > > >
|
std::vector<std::pair<irr::scene::ISceneNode*, int> > > >
|
||||||
|
@ -505,6 +505,7 @@ public:
|
|||||||
const core::vector3df& pivotPoint = core::vector3df(0.0f,0.0f,0.0f) ) = 0;
|
const core::vector3df& pivotPoint = core::vector3df(0.0f,0.0f,0.0f) ) = 0;
|
||||||
|
|
||||||
virtual core::array<SParticle>& getParticles() = 0;
|
virtual core::array<SParticle>& getParticles() = 0;
|
||||||
|
virtual bool getFlips() const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace scene
|
} // end namespace scene
|
||||||
|
@ -508,7 +508,10 @@ void STKParticle::OnRegisterSceneNode()
|
|||||||
Buffer->BoundingBox.reset(AbsoluteTransformation.getTranslation());
|
Buffer->BoundingBox.reset(AbsoluteTransformation.getTranslation());
|
||||||
for (unsigned i = 0; i < m_particles_generating.size(); i++)
|
for (unsigned i = 0; i < m_particles_generating.size(); i++)
|
||||||
{
|
{
|
||||||
if (m_particles_generating[i].m_size == 0.0f)
|
if (m_particles_generating[i].m_size == 0.0f ||
|
||||||
|
std::isnan(m_particles_generating[i].m_position.X) ||
|
||||||
|
std::isnan(m_particles_generating[i].m_position.Y) ||
|
||||||
|
std::isnan(m_particles_generating[i].m_position.Z))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -529,6 +532,12 @@ void STKParticle::OnRegisterSceneNode()
|
|||||||
p.color.setGreen(core::clamp((int)(ret.Y * 255.0f), 0, 255));
|
p.color.setGreen(core::clamp((int)(ret.Y * 255.0f), 0, 255));
|
||||||
p.color.setBlue(core::clamp((int)(ret.Z * 255.0f), 0, 255));
|
p.color.setBlue(core::clamp((int)(ret.Z * 255.0f), 0, 255));
|
||||||
p.color.setAlpha(core::clamp((int)(alpha * 255.0f), 0, 255));
|
p.color.setAlpha(core::clamp((int)(alpha * 255.0f), 0, 255));
|
||||||
|
if (irr_driver->getVideoDriver()->getDriverType() == video::EDT_VULKAN)
|
||||||
|
{
|
||||||
|
// Only used in ge_vulkan_draw_call.cpp
|
||||||
|
p.startTime = i;
|
||||||
|
p.startSize.Width = m_particles_generating[i].m_lifetime;
|
||||||
|
}
|
||||||
Particles.push_back(p);
|
Particles.push_back(p);
|
||||||
}
|
}
|
||||||
core::matrix4 inv(AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE);
|
core::matrix4 inv(AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE);
|
||||||
|
@ -137,7 +137,7 @@ public:
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void setFlips() { m_flips = true; }
|
void setFlips() { m_flips = true; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
bool getFlips() const { return m_flips; }
|
virtual bool getFlips() const { return m_flips; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
unsigned getMaxCount() const { return m_max_count; }
|
unsigned getMaxCount() const { return m_max_count; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user