2013-04-06 96 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