diff --git a/src/graphics/gpuparticles.cpp b/src/graphics/gpuparticles.cpp index 5b06923bd..ade7efcb0 100644 --- a/src/graphics/gpuparticles.cpp +++ b/src/graphics/gpuparticles.cpp @@ -5,9 +5,9 @@ #include #include #include "guiengine/engine.hpp" - + #define COMPONENTCOUNT 8 - + scene::IParticleSystemSceneNode *ParticleSystemProxy::addParticleNode( bool withDefaultEmitter, ISceneNode* parent, s32 id, const core::vector3df& position, @@ -16,16 +16,16 @@ scene::IParticleSystemSceneNode *ParticleSystemProxy::addParticleNode( { if (!parent) parent = irr_driver->getSceneManager()->getRootSceneNode(); - + IParticleSystemSceneNode* node = new ParticleSystemProxy(withDefaultEmitter, parent, irr_driver->getSceneManager(), id, position, rotation, scale); node->drop(); - + return node; } - + GLuint ParticleSystemProxy::quad_vertex_buffer = 0; - + ParticleSystemProxy::ParticleSystemProxy(bool createDefaultEmitter, ISceneNode* parent, scene::ISceneManager* mgr, s32 id, const core::vector3df& position, @@ -38,11 +38,11 @@ ParticleSystemProxy::ParticleSystemProxy(bool createDefaultEmitter, glGenVertexArrays(1, ¤t_rendering_vao); glGenVertexArrays(1, &non_current_rendering_vao); size_increase_factor = 0.; - + m_color_from[0] = m_color_from[1] = m_color_from[2] = 1.0; m_color_to[0] = m_color_to[1] = m_color_to[2] = 1.0; - - + + // We set these later but avoid coverity report them heighmapbuffer = 0; heightmaptexture = 0; @@ -54,7 +54,7 @@ ParticleSystemProxy::ParticleSystemProxy(bool createDefaultEmitter, track_x_len = 0; track_z_len = 0; texture = 0; - + if (quad_vertex_buffer) return; static const GLfloat quad_vertex[] = { @@ -68,7 +68,7 @@ ParticleSystemProxy::ParticleSystemProxy(bool createDefaultEmitter, glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertex), quad_vertex, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); } - + ParticleSystemProxy::~ParticleSystemProxy() { glDeleteBuffers(2, tfb_buffers); @@ -80,17 +80,17 @@ ParticleSystemProxy::~ParticleSystemProxy() if (heightmaptexture) glDeleteTextures(1, &heightmaptexture); } - + void ParticleSystemProxy::setFlip() { flip = true; } - + void ParticleSystemProxy::setHeightmap(const std::vector > &hm, float f1, float f2, float f3, float f4) { track_x = f1, track_z = f2, track_x_len = f3, track_z_len = f4; - + unsigned width = hm.size(); unsigned height = hm[0].size(); float *hm_array = new float[width * height]; @@ -109,34 +109,34 @@ void ParticleSystemProxy::setHeightmap(const std::vector > &h glBindTexture(GL_TEXTURE_BUFFER, heightmaptexture); glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, heighmapbuffer); glBindBuffer(GL_TEXTURE_BUFFER, 0); - + delete[] hm_array; } - + static void generateLifetimeSizeDirection(scene::IParticleEmitter *emitter, float &lifetime, float &size, float &dirX, float &dirY, float &dirZ) { float sizeMin = emitter->getMinStartSize().Height; float sizeMax = emitter->getMaxStartSize().Height; float lifetime_range = float(emitter->getMaxLifeTime() - emitter->getMinLifeTime()); - + lifetime = os::Randomizer::frand() * lifetime_range; lifetime += emitter->getMinLifeTime(); - + size = os::Randomizer::frand(); size *= (sizeMax - sizeMin); size += sizeMin; - + core::vector3df particledir = emitter->getDirection(); particledir.rotateXYBy(os::Randomizer::frand() * emitter->getMaxAngleDegrees()); particledir.rotateYZBy(os::Randomizer::frand() * emitter->getMaxAngleDegrees()); particledir.rotateXZBy(os::Randomizer::frand() * emitter->getMaxAngleDegrees()); - + dirX = particledir.X; dirY = particledir.Y; dirZ = particledir.Z; } - + struct ParticleData { float PositionX; @@ -148,11 +148,11 @@ struct ParticleData float DirectionZ; float Size; }; - + void ParticleSystemProxy::generateParticlesFromPointEmitter(scene::IParticlePointEmitter *emitter) { ParticleData *particles = new ParticleData[count], *initialvalue = new ParticleData[count]; - + for (unsigned i = 0; i < count; i++) { particles[i].PositionX = 0; @@ -160,15 +160,15 @@ void ParticleSystemProxy::generateParticlesFromPointEmitter(scene::IParticlePoin particles[i].PositionZ = 0; // Initial lifetime is >1 particles[i].Lifetime = 2.; - + memcpy(&(initialvalue[i].PositionX), &(particles[i].PositionX), 3 * sizeof(float)); - + generateLifetimeSizeDirection(emitter, initialvalue[i].Lifetime, initialvalue[i].Size, initialvalue[i].DirectionX, initialvalue[i].DirectionY, initialvalue[i].DirectionZ); - + memcpy(&(particles[i].DirectionX), &(initialvalue[i].DirectionX), 4 * sizeof(float)); } - + glBindBuffer(GL_ARRAY_BUFFER, initial_values_buffer); glBufferData(GL_ARRAY_BUFFER, count * sizeof(ParticleData), initialvalue, GL_STREAM_DRAW); glBindBuffer(GL_ARRAY_BUFFER, tfb_buffers[0]); @@ -178,20 +178,20 @@ void ParticleSystemProxy::generateParticlesFromPointEmitter(scene::IParticlePoin delete[] particles; delete[] initialvalue; } - + void ParticleSystemProxy::generateParticlesFromBoxEmitter(scene::IParticleBoxEmitter *emitter) { ParticleData *particles = new ParticleData[count], *initialvalue = new ParticleData[count]; - + const core::vector3df& extent = emitter->getBox().getExtent(); - + for (unsigned i = 0; i < count; i++) { particles[i].PositionX = emitter->getBox().MinEdge.X + os::Randomizer::frand() * extent.X; particles[i].PositionY = emitter->getBox().MinEdge.Y + os::Randomizer::frand() * extent.Y; particles[i].PositionZ = emitter->getBox().MinEdge.Z + os::Randomizer::frand() * extent.Z; // Initial lifetime is random particles[i].Lifetime = os::Randomizer::frand(); - + memcpy(&(initialvalue[i].PositionX), &(particles[i].PositionX), 3 * sizeof(float)); generateLifetimeSizeDirection(emitter, initialvalue[i].Lifetime, initialvalue[i].Size, initialvalue[i].DirectionX, initialvalue[i].DirectionY, initialvalue[i].DirectionZ); @@ -206,27 +206,27 @@ void ParticleSystemProxy::generateParticlesFromBoxEmitter(scene::IParticleBoxEmi delete[] particles; delete[] initialvalue; } - + void ParticleSystemProxy::generateParticlesFromSphereEmitter(scene::IParticleSphereEmitter *emitter) { ParticleData *particles = new ParticleData[count], *initialvalue = new ParticleData[count]; - + for (unsigned i = 0; i < count; i++) { // Random distance from center const f32 distance = os::Randomizer::frand() * emitter->getRadius(); - + // Random direction from center vector3df pos = emitter->getCenter() + distance; pos.rotateXYBy(os::Randomizer::frand() * 360.f, emitter->getCenter()); pos.rotateYZBy(os::Randomizer::frand() * 360.f, emitter->getCenter()); pos.rotateXZBy(os::Randomizer::frand() * 360.f, emitter->getCenter()); - + particles[i].PositionX = pos.X; particles[i].PositionY = pos.Y; particles[i].PositionZ = pos.Z; // Initial lifetime is > 1 particles[i].Lifetime = 2.; - + memcpy(&(initialvalue[i].PositionX), &(particles[i].PositionX), 3 * sizeof(float)); generateLifetimeSizeDirection(emitter, initialvalue[i].Lifetime, initialvalue[i].Size, initialvalue[i].DirectionX, initialvalue[i].DirectionY, initialvalue[i].DirectionZ); @@ -241,7 +241,7 @@ void ParticleSystemProxy::generateParticlesFromSphereEmitter(scene::IParticleSph delete[] particles; delete[] initialvalue; } - + static bool isGPUParticleType(scene::E_PARTICLE_EMITTER_TYPE type) { switch (type) @@ -257,7 +257,7 @@ static bool isGPUParticleType(scene::E_PARTICLE_EMITTER_TYPE type) template void setPositionQuadAttributes(GLuint quad_vbo, GLuint position_vbo) -{ +{ glBindBuffer(GL_ARRAY_BUFFER, quad_vbo); glEnableVertexAttribArray(T::attrib_quadcorner); glVertexAttribPointer(T::attrib_quadcorner, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); @@ -275,21 +275,21 @@ void setPositionQuadAttributes(GLuint quad_vbo, GLuint position_vbo) glVertexAttribPointer(T::attrib_sz, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid *)(7 * sizeof(float))); glVertexAttribDivisor(T::attrib_sz, 1); } - + void ParticleSystemProxy::FlipParticleVAOBind(GLuint PositionBuffer, GLuint QuaternionBuffer) -{ - setPositionQuadAttributes(quad_vertex_buffer, PositionBuffer); +{ + setPositionQuadAttributes(quad_vertex_buffer, PositionBuffer); glEnableVertexAttribArray(ParticleShader::FlipParticleRender::attrib_rotationvec); glEnableVertexAttribArray(ParticleShader::FlipParticleRender::attrib_anglespeed); - + glBindBuffer(GL_ARRAY_BUFFER, QuaternionBuffer); glVertexAttribPointer(ParticleShader::FlipParticleRender::attrib_rotationvec, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); glVertexAttribPointer(ParticleShader::FlipParticleRender::attrib_anglespeed, 1, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid *)(3 * sizeof(float))); glVertexAttribDivisor(ParticleShader::FlipParticleRender::attrib_rotationvec, 1); - glVertexAttribDivisor(ParticleShader::FlipParticleRender::attrib_anglespeed, 1); + glVertexAttribDivisor(ParticleShader::FlipParticleRender::attrib_anglespeed, 1); } - + void ParticleSystemProxy::SimpleParticleVAOBind(GLuint PositionBuffer) { setPositionQuadAttributes(quad_vertex_buffer, PositionBuffer); @@ -321,18 +321,18 @@ void setSimulationBind(GLuint position_vbo, GLuint initialValues_vbo) glEnableVertexAttribArray(T::attrib_initial_size); glVertexAttribPointer(T::attrib_initial_size, 1, GL_FLOAT, GL_FALSE, sizeof(ParticleData), (GLvoid*)(7 * sizeof(float))); } - + void ParticleSystemProxy::SimpleSimulationBind(GLuint PositionBuffer, GLuint InitialValuesBuffer) { setSimulationBind(PositionBuffer, InitialValuesBuffer); } - + void ParticleSystemProxy::HeightmapSimulationBind(GLuint PositionBuffer, GLuint InitialValuesBuffer) { setSimulationBind(PositionBuffer, InitialValuesBuffer); } - - + + void ParticleSystemProxy::setEmitter(scene::IParticleEmitter* emitter) { CParticleSystemSceneNode::setEmitter(emitter); @@ -340,7 +340,7 @@ void ParticleSystemProxy::setEmitter(scene::IParticleEmitter* emitter) return; has_height_map = false; flip = false; - + count = emitter->getMaxParticlesPerSecond() * emitter->getMaxLifeTime() / 1000; switch (emitter->getType()) { @@ -356,14 +356,14 @@ void ParticleSystemProxy::setEmitter(scene::IParticleEmitter* emitter) default: assert(0 && "Wrong particle type"); } - + glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); - video::ITexture *tex = getMaterial(0).getTexture(0); - transformTexturesTosRGB(tex); + video::ITexture *tex = getMaterial(0).getTexture(0); + transformTexturesTosRGB(tex); texture = getTextureGLuint(getMaterial(0).getTexture(0)); } - + void ParticleSystemProxy::simulateHeightmap() { int timediff = int(GUIEngine::getLatestDt() * 1000.f); @@ -371,7 +371,7 @@ void ParticleSystemProxy::simulateHeightmap() core::matrix4 matrix = getAbsoluteTransformation(); glUseProgram(ParticleShader::HeightmapSimulationShader::Program); glEnable(GL_RASTERIZER_DISCARD); - + glUniform1i(ParticleShader::HeightmapSimulationShader::uniform_dt, timediff); glUniform1i(ParticleShader::HeightmapSimulationShader::uniform_level, active_count); glUniformMatrix4fv(ParticleShader::HeightmapSimulationShader::uniform_sourcematrix, 1, GL_FALSE, matrix.pointer()); @@ -383,21 +383,21 @@ void ParticleSystemProxy::simulateHeightmap() glUniform1f(ParticleShader::HeightmapSimulationShader::uniform_track_z, track_z); glUniform1f(ParticleShader::HeightmapSimulationShader::uniform_track_x_len, track_x_len); glUniform1f(ParticleShader::HeightmapSimulationShader::uniform_track_z_len, track_z_len); - + glBindVertexArray(current_simulation_vao); glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfb_buffers[1]); - + glBeginTransformFeedback(GL_POINTS); glDrawArrays(GL_POINTS, 0, count); glEndTransformFeedback(); glBindVertexArray(0); - + glDisable(GL_RASTERIZER_DISCARD); std::swap(tfb_buffers[0], tfb_buffers[1]); std::swap(current_rendering_vao, non_current_rendering_vao); std::swap(current_simulation_vao, non_current_simulation_vao); } - + void ParticleSystemProxy::simulateNoHeightmap() { int timediff = int(GUIEngine::getLatestDt() * 1000.f); @@ -405,26 +405,26 @@ void ParticleSystemProxy::simulateNoHeightmap() core::matrix4 matrix = getAbsoluteTransformation(); glUseProgram(ParticleShader::SimpleSimulationShader::Program); glEnable(GL_RASTERIZER_DISCARD); - + glUniform1i(ParticleShader::SimpleSimulationShader::uniform_dt, timediff); glUniform1i(ParticleShader::SimpleSimulationShader::uniform_level, active_count); glUniformMatrix4fv(ParticleShader::SimpleSimulationShader::uniform_sourcematrix, 1, GL_FALSE, matrix.pointer()); glUniform1f(ParticleShader::SimpleSimulationShader::uniform_size_increase_factor, size_increase_factor); - + glBindVertexArray(current_simulation_vao); glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfb_buffers[1]); - + glBeginTransformFeedback(GL_POINTS); glDrawArrays(GL_POINTS, 0, count); glEndTransformFeedback(); glBindVertexArray(0); - + glDisable(GL_RASTERIZER_DISCARD); std::swap(tfb_buffers[0], tfb_buffers[1]); std::swap(current_rendering_vao, non_current_rendering_vao); std::swap(current_simulation_vao, non_current_simulation_vao); } - + void ParticleSystemProxy::simulate() { if (has_height_map) @@ -432,26 +432,26 @@ void ParticleSystemProxy::simulate() else simulateNoHeightmap(); } - + void ParticleSystemProxy::drawFlip() { glBlendFunc(GL_ONE, GL_ONE); glUseProgram(ParticleShader::FlipParticleRender::Program); - + float screen[2] = { (float)UserConfigParams::m_width, (float)UserConfigParams::m_height }; - + setTexture(0, texture, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR); setTexture(1, irr_driver->getDepthStencilTexture(), GL_NEAREST, GL_NEAREST); - + ParticleShader::FlipParticleRender::setUniforms(irr_driver->getViewMatrix(), irr_driver->getProjMatrix(), irr_driver->getInvProjMatrix(), screen[0], screen[1], 0, 1); - + glBindVertexArray(current_rendering_vao); glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count); } - + void ParticleSystemProxy::drawNotFlip() { if (m_alpha_additive) @@ -459,22 +459,22 @@ void ParticleSystemProxy::drawNotFlip() else glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glUseProgram(ParticleShader::SimpleParticleRender::Program); - + float screen[2] = { (float)UserConfigParams::m_width, (float)UserConfigParams::m_height }; - + setTexture(0, texture, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR); setTexture(1, irr_driver->getDepthStencilTexture(), GL_NEAREST, GL_NEAREST); - + ParticleShader::SimpleParticleRender::setUniforms(irr_driver->getViewMatrix(), irr_driver->getProjMatrix(), irr_driver->getInvProjMatrix(), screen[0], screen[1], 0, 1, this); - + glBindVertexArray(current_rendering_vao); glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count); } - + void ParticleSystemProxy::draw() { if (flip) @@ -482,14 +482,14 @@ void ParticleSystemProxy::draw() else drawNotFlip(); } - + void ParticleSystemProxy::generateVAOs() { glGenVertexArrays(1, ¤t_rendering_vao); glGenVertexArrays(1, &non_current_rendering_vao); glGenVertexArrays(1, ¤t_simulation_vao); glGenVertexArrays(1, &non_current_simulation_vao); - + glBindVertexArray(current_simulation_vao); if (has_height_map) HeightmapSimulationBind(tfb_buffers[0], initial_values_buffer); @@ -500,7 +500,7 @@ void ParticleSystemProxy::generateVAOs() HeightmapSimulationBind(tfb_buffers[1], initial_values_buffer); else SimpleSimulationBind(tfb_buffers[1], initial_values_buffer); - + float *quaternions = new float[4 * count]; glBindVertexArray(0); if (flip) @@ -508,7 +508,7 @@ void ParticleSystemProxy::generateVAOs() for (unsigned i = 0; i < count; i++) { core::vector3df rotationdir(0., 1., 0.); - + quaternions[4 * i] = rotationdir.X; quaternions[4 * i + 1] = rotationdir.Y; quaternions[4 * i + 2] = rotationdir.Z; @@ -518,23 +518,23 @@ void ParticleSystemProxy::generateVAOs() glBindBuffer(GL_ARRAY_BUFFER, quaternionsbuffer); glBufferData(GL_ARRAY_BUFFER, 4 * count * sizeof(float), quaternions, GL_STATIC_DRAW); } - + glBindVertexArray(current_rendering_vao); if (flip) FlipParticleVAOBind(tfb_buffers[0], quaternionsbuffer); else SimpleParticleVAOBind(tfb_buffers[0]); - + glBindVertexArray(non_current_rendering_vao); if (flip) FlipParticleVAOBind(tfb_buffers[1], quaternionsbuffer); else SimpleParticleVAOBind(tfb_buffers[1]); glBindVertexArray(0); - + delete[] quaternions; } - + void ParticleSystemProxy::render() { if (!getEmitter() || !isGPUParticleType(getEmitter()->getType())) { @@ -546,11 +546,11 @@ void ParticleSystemProxy::render() { simulate(); draw(); } - + void ParticleSystemProxy::OnRegisterSceneNode() { doParticleSystem(os::Timer::getTime()); - + if (IsVisible && (Particles.size() != 0)) { SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT_EFFECT);