2013-04-06 3 views
0

У меня проблема с двигателем частиц, который я делаю. С двигателем вы можете добавить в двигатель более одного излучателя, и идея состоит в том, что каждая система частиц может излучать свои собственные частицы.Проблемы с рисунком OpenGL VBO

Проблема, которую я получаю, заключается в том, что когда я добавляю вторую систему частиц, кажется, что на нее влияет первый рисунок, под которым я подразумеваю, что он не нарисован вообще. Вызов вызова каждой системы частиц называется правильно.

Я думаю, что проблема заключается в том, что, хотя несколько VBO создаются, используется только один.

Я покажу важные части моих функций, которые влияют на VBOs. В моем шейдере используется однородное место для хранения матриц 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? или я полностью ошибаюсь. Я использовал отладчик шейдеров и обе VBOs вызывающе существуют.

+0

Так что VboId и т. Д. Переменная-член какого-либо класса или глобальная переменная? т. е. есть ли у вас отдельные переменные VboId для каждой системы частиц? это не ясно в вашем коде, поскольку вы не показываете объявления переменных. – Pete

+0

@pete, да все необходимые переменные openGL хранятся в системе частиц eahc. Я добавлю необходимые объяснения слушателей. – Bushes

+0

они находятся в заголовке или находятся в классе с экземпляром на систему частиц? Пока неясно - есть ли у вас класс ParticleSystem * или что-то еще? – Pete

ответ

0

вам необходимо правильно настроить вершинную attribs перед каждым вызовом отрисовки - то есть, вы должны вызвать glBindBuffer с последующим glEnableVertexArray & glVertexAttribPointer для каждого из атрибутов перед каждым вызовом отрисовки. в коде, который вы отправили, это происходит только для позиции частиц, но не для атрибута WVP_LOCATION, который, по-видимому, содержит ваши матрицы преобразования (вы загружаете данные на GPU через glBufferData, но не настраиваете атрибут) - это означает, что, как только у вас будет более одной системы частиц, только матрицы преобразования вашей второй системы частиц будут доступны для рендеринга.

Один из сторон не то, что вы пытаетесь сделать здесь, кажется довольно неэффективным - вы по существу нажимаете одну матрицу преобразования на GPU для каждой из ваших частиц за каждый кадр. В зависимости от того, сколько частиц вы хотите, это убьет вашу производительность - вы должны рассмотреть возможность обновления положения частицы и т. Д. С помощью transform feedback.

Редактировать: только что понял, что ссылка wiki opengl действительно не объясняет многое. обратная связь преобразования - способ записи вершинных шейдерных выходов (или, если присутствует шейдер геометрии/тесселяции, этот вывод будет записан вместо этого). Выходные переменные записываются в VBO - впоследствии они могут использоваться для рендеринга, как и любой другой атрибут вершины. Вся концепция чрезвычайно похожа на использование объекта framebuffer для записи фрагментов шейдера фрагмента; Это позволяет системам частиц, которые полностью существуют на GPU, с вершинным шейдером, вычисляющим обновленную позицию, время жизни & других атрибутов в каждом кадре.Очень хороший учебник, в котором показаны основные настройки такой обратной связи с преобразованием, можно найти: here

+0

Эта ссылка не очень описательная. Не могли бы вы расширить его? – Hydronium