2013-04-06 94 views
0

我在使用我正在制作的粒子引擎时遇到问题。通过引擎,您可以将多个发射器添加到引擎中,每个粒子系统都可以发射自己的粒子。OpenGL VBO绘图问题

但是我得到的问题是,当我添加第二个粒子系统时,第一个图的绘制似乎受到影响,我的意思是它没有绘制。每个粒子系统的绘图调用都被正确调用。

但是我认为问题在于,尽管创建了多个VBO,但实际上只使用了一个。

我将展示影响维也纳各组织的职能的重要部分。我的着色器使用统一的位置来存储WVP矩阵。我还应该提到每个粒子系统应该使用自己的着色器程序。

下面这是我在创建粒子系统时称为initializeBuffers功能:

void ParticleSystem::InitializeBuffers() 
{ 
    glGenVertexArrays(1, &VaoId); 
    glBindVertexArray(VaoId); 

    //glGenBuffers(1, &VboId); 
    glGenBuffers(1, &PositionBufferId); 
    glGenBuffers(1, &IndexBufferId); 
    glGenBuffers(1, &WVPId); 

    std::list<Particle>::iterator iterator = particles.begin(); 
    //positions.reserve(5); 

    for (std::list<Particle>::iterator iterator = particles.begin(), end = particles.end(); iterator != end; ++iterator) 
    { 
     positions.push_back(iterator->GetPosition()); 
     //verticesToDraw.insert(verticesToDraw.end(), iterator->GetVertices()->begin(), iterator->GetVertices()->end()); 
     indicesToDraw.insert(indicesToDraw.end(), iterator->GetIndices()->begin(), iterator->GetIndices()->end()); 
    } 


    //glBindBuffer(GL_ARRAY_BUFFER, VboId); 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicesToDraw[0]) * indicesToDraw.size(), &indicesToDraw[0], GL_STATIC_DRAW); 
    glBindBuffer(GL_ARRAY_BUFFER, WVPId); 

    for (unsigned int i = 0; i < 4 ; i++) { 
     glEnableVertexAttribArray(WVP_LOCATION + i); 
     glVertexAttribPointer(WVP_LOCATION + i, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (const GLvoid*)(sizeof(GLfloat) * i * 4)); 
     glVertexAttribDivisor(WVP_LOCATION + i, 1); 
    } 

    for(std::list<BaseBuildingBlock*>::iterator iterator = buildingBlocks.begin(), end = buildingBlocks.end(); iterator != end; ++iterator) 
    { 
     (*iterator)->InitializeBuffer(programId); 
    } 

    /* 
    glBindBuffer(GL_ARRAY_BUFFER, WorldId); 

    for (unsigned int i = 0; i < 4 ; i++) { 
    glEnableVertexAttribArray(WORLD_LOCATION + i); 
    glVertexAttribPointer(WORLD_LOCATION + i, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (const GLvoid*)(sizeof(GLfloat) * i * 4)); 
    glVertexAttribDivisor(WORLD_LOCATION + i, 1); 
    } 
    */ 
    //return GLCheckError(); 
} 

这是绘制函数和实际绘制实例化元素的代码,所述WVP矩阵用前面所述粒子系统形成在函数中。

void ParticleSystem::Draw(Matrix4f perspectiveCameraMatrix) 
{ 
    // scale TEST 
    //GLint gScaleLocation = glGetUniformLocation(program, "gScale"); 
    //assert(gScaleLocation != 0xFFFFFFFF); 
    //glUniform1f(gScaleLocation, scale); 

    //Pipeline p; 
    //Matrix4f* WVPMatrices = new Matrix4f[particles.size()]; 
    //Matrix4f* WorldMatrices = new Matrix4f[particles.size()]; 

    WVPMatrices.clear(); 
    WorldMatrices.clear(); 

    glUseProgram(0); 

    glUseProgram(programId); 

    //Matrix4f perspectiveMatrix; 
    //perspectiveMatrix.BuildPerspProjMat(90,1, 0.01, 200, 100 - 0 /*getWidth()/32*/, 100 - 0 /*getHeight()/32*/); 


    //******************************************************************************************************** 
    // Method 1 

    // Think I need to next define a camera position. 

    if(particles.size() == 0) 
    { 
     return; 
    } 

    verticesToDraw.clear(); 


    Matrix4f scaleMatrix; 
    Matrix4f worldMatrix; 
    Matrix4f rotateMatrix; 
    Matrix4f finalMatrix; 

    //ColourId = glGetUniformLocation(programId, "UniformColour"); 


    int i = 0; 



    for (std::list<Particle>::iterator iterator = particles.begin(), end = particles.end(); iterator != end; ++iterator) 
    { 

     verticesToDraw = *iterator->GetVertices(); 
     indicesToDraw = *iterator->GetIndices(); 
     //positions.push_back(iterator->GetPosition()); 
     worldMatrix.InitTranslationTransform(iterator->GetPosition().x, iterator->GetPosition().y, iterator->GetPosition().z); 
     rotateMatrix.InitRotateTransform(iterator->GetRotation().x, iterator->GetRotation().y, iterator->GetRotation().z); 
     scaleMatrix.InitScaleTransform(iterator->GetScale().x, iterator->GetScale().y, iterator->GetScale().z); 
     finalMatrix = perspectiveCameraMatrix * worldMatrix * rotateMatrix * scaleMatrix; 
     //p.WorldPos(iterator->GetPosition()); 
     //p.Rotate(iterator->GetRotation()); 
     WVPMatrices.push_back(finalMatrix.Transpose()); 

     /*glUniform4f(ColourId, iterator->GetColour().r, iterator->GetColour().g, iterator->GetColour().b, 
     iterator->GetColour().a);*/ 
     //WorldMatrices[i] = p.GetWorldTrans(); 
     i++; 

     //iterator->Draw(); 
    } 


    //glEnableVertexAttribArray(0); 

    if(colourOverLifeBuildingBlock != NULL) 
    { 
     colourOverLifeBuildingBlock->Test(); 
    } 

    glBindBuffer(GL_ARRAY_BUFFER, VboId); 
    glBufferData(GL_ARRAY_BUFFER, verticesToDraw.size() * sizeof(verticesToDraw[0]), &verticesToDraw.front(), GL_STATIC_DRAW); 
    glEnableVertexAttribArray(POSITION_LOCATION); 
    glVertexAttribPointer(POSITION_LOCATION, 3, GL_FLOAT, GL_FALSE, 0, 0); 

    int size = particles.size(); 

    glBindBuffer(GL_ARRAY_BUFFER, WVPId); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(Matrix4f) * size, &WVPMatrices.front(), GL_DYNAMIC_DRAW); 

    glDrawElementsInstanced(GL_TRIANGLES, indicesToDraw.size(), GL_UNSIGNED_BYTE, 0, particles.size()); 

    glBindBuffer(GL_ARRAY_BUFFER, 0); 

    //glDisableVertexAttribArray(0); 
    //glFlush(); 

} 

粒子系统整个头部低于:

#include <gl\glew.h> 
#include <array> 
#include <vector> 

class ParticleSystem 
{ 

public: 
    ParticleSystem(Vector3 pos, Quaternion rot, float spawnRate, int particlesToSpawn); // Constructs a particle system. 
    ~ParticleSystem(); // Destructor. 
    void Update(float elapsedTime); // Updates the particle system. 
    void Draw(Matrix4f perspectiveMatrix); // Draw the particle system 
    void CreateShaders(); 
    void InitializeBuffers(); 

    // Long amount of get sets. 
    /*float* GetMinLifeTime(); 
    void SetMinLifeTime(float lt); 
    float* GetMaxLifeTime(); 
    void SetMaxLifeTime(float lt);*/ 
    int* GetParticlesToSpawnAtATime(); 
    void SetParticlesToSpawnAtATime(int particlesToSpawn); 
    float* GetSpawnRate(); 
    void SetSpawnRate(float spawnRate); 
    Vector3* GetPosition(); 
    void SetPosition(Vector3 newPosition); 
    Quaternion* GetRotation(); 
    void SetRotation(Quaternion rotation); 
    std::list<BaseBuildingBlock*> GetBuildingBlocks(); 

    VelocityBuildingBlock* GetVelocityBuilding(); 
    ColourOverLifeBuildingBlock* GetColourOverLifeBuildingBlock(); 
    LifeTimeBuildingBlock* GetLifeTimeBuildingBlock(); 
    UniformColourBuildingBlock* GetUniformColourBuildingBlock(); 
    ScaleBuildingBlock* GetScaleBuildingBlock(); 
    /*Vector3* GetMinVelocity(); 
    void SetMinVelocity(Vector3 min); 
    Vector3* GetMaxVelocity(); 
    void SetMaxVelocity(Vector3 maxVelocity);*/ 
    Vector3 GetMinParticleStartPoint(); 
    void SetMinParticleStartPoint(Vector3 minParticleStartPoint); 
    Vector3 GetMaxParticleStartPoint(); 
    void SetMaxParticleStartPoint(Vector3 maxParticleStartPoint); 
    bool CreateColourOverLifeBuildingBlock(); 
    bool DeleteColourOverLifeBuildingBlock(); 
    bool CreateUniformColourBuildingBlock(); 
    bool DeleteUniformColourBuildingBlock(); 
    bool CreateScaleBuildingBlock(); 
    bool DeleteScaleBuildingBlock(); 


    /*Colour GetStartColour(); 
    void SetStartColour(Colour startColour); 
    Colour GetEndColour(); 
    void SetEndColour(Colour endColour);*/ 
    Vector3* GetMinParticleRotationAmountPerFrame(); 
    void SetMinParticleRotationAmountPerFrame(Vector3 minParticleRotationAmount); 
    Vector3* GetMaxParticleRotationAmountPerFrame(); 
    void SetMaxParticleRotationAmountPerFrame(Vector3 maxParticleRotationAmount); 
    void Save(TiXmlElement* element); 

private: 
    // Spawns a particle. 
    void SpawnParticle(); 

    GLuint VaoId; 
    GLuint VboId; 
    GLuint IndexBufferId; 
    GLuint PositionBufferId; 
    GLuint WVPId; 
    GLenum programId; 

    std::vector<GLfloat> verticesToDraw; 
    std::vector<GLubyte> indicesToDraw; 
    std::vector<Vector3> positions; 
    std::vector<Matrix4f> WVPMatrices; 
    std::vector<Matrix4f> WorldMatrices; 

    std::list<Particle> particles; // List of particles 
    Vector3 position; // position of the emitter 
    Quaternion rotation; // rotation of the emitter. 
    float spawnRate; // spawnrate of the emitter. 
    int particlesToSpawnAtATime; // The amount of particles to spawn at a time. 
    float minLifeTime; // The minimum time a particle can live for. 
    float maxLifeTime; // The maximum time a particle can live for. 
    float timer; // Timer 
    ShaderCreator* shaderCreator; 

    //Vector3 minVelocity; // The minimum velocity a particle can have. 
    //Vector3 maxVelocity; // The maximum velocity a particle can have/ 



    //std::list<BaseBuildingBlock> buildingBlocks; 

    // I'm thinking of eventually making a list of baseBuildingBlocks. 
    std::list<BaseBuildingBlock*> buildingBlocks; 
    VelocityBuildingBlock* velocityBuildingBlock; 
    ColourOverLifeBuildingBlock* colourOverLifeBuildingBlock; 
    LifeTimeBuildingBlock* lifeTimeBuildingBlock; 
    UniformColourBuildingBlock* uniformColourBuildingBlock; 
    ScaleBuildingBlock* scaleBuildingBlock; 

    Vector3 minParticleStartPoint; // The minimum position a particle can start at. 
    Vector3 maxParticleStartPoint; // The maximum position a particle can start at. 
    Vector3 minParticleRotationAmountPerFrame; // The minimum amount of rotation that a particle can rotate every frame. 
    Vector3 maxParticleRotationAmountPerFrame; // The maximum amount of rotation that a particle can rotate every frame. 
    Colour startColour; // StartColour is the colour that a particle will start with. 
    Colour endColour; // EndColour is the colour that a particle will end with. 

    //TEST 
    float scale; 

}; 

#endif 

现在我想知道,有没有一些方法,我不得不切换有效的VBO?还是我完全走错了路。我使用了一个着色器调试器,并且两个VBO defiantely都存在。

+0

那么VboId等是某个类的成员变量还是全局变量?即,每个粒子系统都有独立的VboId变量吗?由于您不显示变量声明,因此在代码中不清楚。 – Pete 2013-04-06 11:30:03

+0

@pete,是所有openGL变量都存储在eahc粒子系统中。我会添加必要的听力筛选器。 – Bushes 2013-04-06 11:36:37

+0

他们在标题中,或者他们在一个类中每个粒子系统有一个实例?它仍然不清楚 - 你有ParticleSystem *类吗? – Pete 2013-04-06 13:12:12

回答

0

你需要在每个绘制调用之前正确设置你的顶点attribs - 即,你必须调用glBindBuffer其次glEnableVertexArray & glVertexAttribPointer为每个属性的每个绘图调用之前。在你发布的代码中,这只发生在粒子位置上,而不是显示包含你的转换矩阵的'WVP_LOCATION'属性(你通过glBufferData上传数据到GPU,但是不要设置属性) - 意思是说,一旦有多个粒子系统,只有第二个粒子系统的变换矩阵会被访问用于渲染。

一方不是,你在这里试图做的似乎是相当低效的 - 你基本上推动一个转换矩阵到GPU的每个粒子,每帧。根据您想要的粒子数量,这会导致您的性能下降 - 您应该考虑使用transform feedback来更新粒子的位置等。

编辑:刚才意识到opengl维基链接并没有真正解释很多。变换反馈是一种记录顶点着色器输出的方法(或者,如果存在几何/镶嵌着色器,则会记录该输出)。输出变量被写入VBO中 - 之后,它们可以像其他任何顶点属性一样用于渲染。整个概念与使用帧缓冲区对象记录片段着色器输出非常相似;它允许完全存在于GPU上的粒子系统,顶点着色器计算每个帧中的更新位置,生命期其他属性。一个非常好的教程,它显示了这样一个变换反馈的基本设置,可以发现here

+0

该链接不是很具描述性。你可以扩展它吗? – Hydronium 2013-04-07 01:27:09