Hi all!
I have a very basic particle system using transform feedback buffers (ogl 4.3), based on the code from a tutorial (sorry, can’t post links), but there is one thing that is driving me crazy: why are we calling glVertexAttribPointer in the render methods?
I thought that glVertexAttribPointer is used to define the location and data format for the vertex attributes of the shader, so, I have been always using it during the Init() methods.
But in this example that I found, I have seen that they are calling glVertexAttribPointer in the render methods, for example:
void ParticleSystem::UpdateParticles(float deltaTime)
{
//UpdateEmitters(deltaTime);
Shader *particleSystem_shader = DEMO->shaderManager.shader[particleSystemShader];
particleSystem_shader->use();
particleSystem_shader->setValue("gTime", this->m_time);
particleSystem_shader->setValue("gDeltaTime", deltaTime);
bindRandomTexture(RANDOM_TEXTURE_UNIT);
glEnable(GL_RASTERIZER_DISCARD); // Stop drawing on the screen
glBindBuffer(GL_ARRAY_BUFFER, m_particleBuffer[m_currVB]);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transformFeedback[m_currTFB]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(4);
glEnableVertexAttribArray(5);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)0); // Position (12 bytes)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)12); // Velocity (12 bytes)
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)24); // Color (12 bytes)
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)36); // Lifetime (4 bytes)
glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)40); // Size (4 bytes)
glVertexAttribPointer(5, 1, GL_INT, GL_FALSE, sizeof(Particle), (const GLvoid*)44); // Type (4 bytes)
glBeginTransformFeedback(GL_POINTS);
if (m_isFirst) {
glDrawArrays(GL_POINTS, 0, numEmitters);
m_isFirst = false;
}
else {
glDrawTransformFeedback(GL_POINTS, m_transformFeedback[m_currVB]);
}
glEndTransformFeedback();
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
glDisableVertexAttribArray(5);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
}
or…
void ParticleSystem::RenderParticles(const glm::mat4 &VP, const glm::vec3 &CameraPos)
{
//Use the billboard shader and send variables
Shader *my_shader;
my_shader = DEMO->shaderManager.shader[billboardShader];
my_shader->use();
my_shader->setValue("gCameraPos", CameraPos); // Set camera position
my_shader->setValue("gVP", VP); // Set View Projection Matrix
// Activate texture
m_pTexture->active(0);
m_pTexture->bind();
glDisable(GL_RASTERIZER_DISCARD); // Start drawing on the screen
glBindBuffer(GL_ARRAY_BUFFER, m_particleBuffer[m_currTFB]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)0); // Position
glDrawTransformFeedback(GL_POINTS, m_transformFeedback[m_currTFB]);
glDisableVertexAttribArray(0);
}
Why glVertexAttribPointer is in the render functions? the positions are fixed, they will never change, so… why cannot be in the Init() method?
I have tried changing the calls to glVertexAttribPointer in the Init() method, and removing them (and the glEnable/DisableVertexAttribArray, of course) from the Render() methods, but the render outputs are not good… some particles are shown in wrong positions:
bool ParticleSystem::InitParticleSystem(const glm::vec3 &Pos)
{
this->initPosition = Pos;
Particle* Particles = (Particle*)malloc(sizeof(Particle) * numEmitters);
ZERO_MEM(Particles);
// Init the emitters
for (unsigned int i = 0; i < numEmitters; i++) {
Particles[i].Type = PARTICLE_TYPE_LAUNCHER;
float circle = 2*3.1415f* ( (float)(i+1) / ((float)numEmitters));
Particles[i].Pos = initPosition + glm::vec3(sin(circle), 0, cos(circle));
Particles[i].Vel = glm::vec3(0.0f, 1.0f, 0.0f);
Particles[i].Col = glm::vec3(1.0f, 1.0f, 1.0f);
Particles[i].Size = 1.0;
Particles[i].lifeTime = 0.0f;
}
// Gen the VAO
glGenVertexArrays(1, &m_VAO);
glBindVertexArray(m_VAO);
// Gen buffers
glGenTransformFeedbacks(2, m_transformFeedback); // Transform Feedback object
glGenBuffers(2, m_particleBuffer); // Transform Feedback buffer
for (unsigned int i = 0; i < 2; i++) {
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transformFeedback[i]);
glBindBuffer(GL_ARRAY_BUFFER, m_particleBuffer[i]);
glBufferData(GL_ARRAY_BUFFER, sizeof(Particle)*numMaxParticles, NULL, GL_DYNAMIC_DRAW); // Allocate mem, uploading an empty buffer for all the particles
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Particle)*numEmitters, Particles); // Upload only the emitters to the Buffer
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_particleBuffer[i]);
}
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)0); // Position (12 bytes)
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)12); // Velocity (12 bytes)
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)24); // Color (12 bytes)
glEnableVertexAttribArray(2);
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)36); // Lifetime (4 bytes)
glEnableVertexAttribArray(3);
glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)40); // Size (4 bytes)
glEnableVertexAttribArray(4);
glVertexAttribPointer(5, 1, GL_INT, GL_FALSE, sizeof(Particle), (const GLvoid*)44); // Type (4 bytes)
glEnableVertexAttribArray(5);
free(Particles);
// Make sure the VAO is not changed from the outside
glBindVertexArray(0);
// Some other init calls go here...
[...]
}
Any clue? I’m sure is there a good reason to be in the Render function, but I don’t understand it
- Could be that I am drawing with glDrawTransformFeedback call? and this call needs to define the VertexAttributes on each render?
- Or maybe is because I am using 1 VAO for all, and the 2 render functions are using a different layout? (UpdateParticles uses the 5 attributes, while renderParticles is using only the first attribute [position]). Should this mean that I should use 2 VAO’s?
Thanks in advance!!!