如何渲染实例粒子

时间:2016-07-26 10:01:58

标签: c++ opengl glsl

我制作了粒子系统,但我想让它变得高效。 所以现在我想制作实例粒子,但我遇到了问题。 看起来所有粒子都在同一轨道上移动。

现在看起来如何:

How it looks like 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());

}

以下是我的vs和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);

}

1 个答案:

答案 0 :(得分:1)

您的MVP矩阵对于每个粒子都是常量,因此它们将全部呈现在屏幕上的相同位置。

我相信你之前每个粒子都有不同的顶点位置,并尝试快速更改为使用单个精灵并绘制多个实例,每个粒子一个。请注意,您需要让每个粒子的变换矩阵反映粒子的移动(变换)。

让我们说你的粒子系统有一个MVP矩阵,其中包括整个粒子系统的任何变换。每个粒子都应该有自己的变换矩阵[T]。

所以你的MVP线应该是

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

,其中     [MVP_Particle] = [MVP] x [T]。

使用一些库来乘以矩阵并上传最终矩阵。这看起来应该是这样的

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

现在,当您使用不同的MVP_Particle将相同的VBO发送到着色器时,它们将根据[ParticleTransformMatrix]在不同的位置绘制。

希望这有帮助。