2016-07-26 37 views
0

我制作了粒子系统,但我想使其效率。 所以现在我想制作实例化的粒子,但是我遇到了问题。 它看起来像所有的粒子同时在相同的轨道上移动。如何渲染实例粒子

如何它看起来像现在:

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

我完全同意@NicolBolas。对于小批量的顶点,“顶点数组”比“VBO”快。如果您使用的是NVIDIA®(英伟达™)卡,您可以使用NVIDIA Bindless Extensions,特别是Vertex Buffer Unified Memory,将速度提高约7倍。如果你有兴趣,这里是一个链接到PDF http://developer.download.nvidia.com/opengl/tutorials/bindless_graphics.pdf – Harish

回答

1

您的MVP矩阵对于每个粒子都是不变的,所以它们都将被渲染到屏幕上的相同位置。

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

可以说你的粒子系统有一个MVP矩阵,它包括整个粒子系统的任何转换。每个粒子应该有它自己的变换矩阵[T]。

所以你为MVP线应该是

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

其中 [MVP_Particle] = [MVP]×[T]。

使用一些库来增加矩阵并上传最终矩阵。这应该是这个样子

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

现在,当你发送相同的VBO与不同MVP_Particle着色器,它们将在不同的地方根据[ParticleTransformMatrix]绘制。

希望这会有所帮助。