Jay Kop
Jay Kop

Reputation: 1

How to render Instance Particle

I made particle system but I want to make it efficient. So now I want to make instanced particle but I got a problem. It looks like all particles move on same track, at the same time.

How it looks like now:

How it looks like now

So I have tried to make them separated but I don't get it.

This is how my particle works for now.

GLfloat m_vertex_buffer_data[] =
{
//      X       Y       Z       U       V
     -.5f,   -.5f,    0.f,    0.f,    0.f,  
     -.5f,    .5f,    0.f,    0.f,    1.f,  
      .5f,    .5f,    0.f,    1.f,    1.f,   
      .5f,   -.5f,    0.f,    1.f,    0.f
};

void Scene::DrawParticle(Emitter* emitter)
{    
  for (auto it = emitter->GetParticleContainer().begin();
    it != emitter->GetParticleContainer().end(); ++it)
  {
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);

    // Update pipeline
    Pipeline(*it);
    vec4 sptColor = (*it)->GetColor();

    glUniformMatrix4fv(m_GSM->GetGLManager()->GetUnifrom(TRANSFORM), 1, GL_FALSE, &m_mvp.m_member[0][0]);
    glUniformMatrix4fv(m_GSM->GetGLManager()->GetUnifrom(UV), 1, GL_FALSE, &m_animation.m_member[0][0]);
    glUniform4f(m_GSM->GetGLManager()->GetUnifrom(COLOR), sptColor.x, sptColor.y, sptColor.z, (*it)->m_life);

    emitter->Update((*it));
  }

  //Refresh the buffer data
  glBufferData(GL_ARRAY_BUFFER, emitter->GetNumOfParticle() * sizeof(m_vertex_buffer_data), NULL, GL_STREAM_DRAW); 
  glBufferSubData(GL_ARRAY_BUFFER, 0, emitter->GetNumOfParticle() * sizeof(m_vertex_buffer_data), m_vertex_buffer_data);

  // Bind our texture in Texture Unit 0
  glBindTexture(GL_TEXTURE_2D, emitter->GetTexture()->GetTexId());

  // Draw quads
  glDrawArraysInstanced(GL_QUADS, 0, 4, emitter->GetNumOfParticle());

}

The followings are my vs and fs. vs;

#version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertTexCoord;

// Values that stay constant for the whole mesh.
uniform vec4 Color ;
uniform mat4 MVP;
uniform mat4 Animation;

//Output data
out vec4 fragmentColor;
out vec2 fragTexCoord;

void main(){

// Set model vertex
gl_Position = MVP * vec4(vertexPosition_modelspace, 1);

// Set Color
fragmentColor = Color;

// Set texture coordinate
vec4 newTexCoord = Animation * vec4(vertTexCoord, 0, 1);

fragTexCoord = vec2(newTexCoord.x, -newTexCoord.y);
}

fs;

#version 330 core

// interpolated valuse form the vertex shaders
in vec4 fragmentColor;
in vec2 fragTexCoord;

//Texture ID
uniform sampler2D Texture;

// Ouput data
out vec4 finalColor;

void main()
{

finalColor = fragmentColor * texture(Texture, fragTexCoord);

}

Upvotes: 0

Views: 317

Answers (1)

Harish
Harish

Reputation: 974

Your MVP matrix is constant for every particle, so they will all be rendered at the same position on the screen.

I believe you had each particle have a different vertex position before and tried to quickly change to using a single sprite and drawing multiple instances of it, one for each particle. Please note that you then need to have the transformation matrix for each particle reflect the movement (transform) of the particle.

Lets say your particle system has an MVP matrix, which includes any transformation the whole particle system has. Each particle should have its own Transformation Matrix [T].

so your line for MVP should be

glUniformMatrix4fv(m_GSM->GetGLManager()->GetUnifrom(TRANSFORM), 1, GL_FALSE, &MVP_Particle[0][0]);

where [MVP_Particle] = [MVP] x [T].

use some library to multiply the matrices and upload the final matrix. This should look something like this

[MVP_Particle] = [Projection] * [View/Camera] * [SystemTransformMatrix] * [ParticleTransformMatrix]

Now when you send the same VBO to the shader with different MVP_Particle, they will be drawn at different places depending on the [ParticleTransformMatrix].

Hope this helps.

Upvotes: 1

Related Questions