#include "particle_batch.hpp" #include // TODO: use VAO's as soon as this is working int getDivisorForIndex(int index) { return (index == 0) ? 1 : 4; } namespace endofthejedi { ParticleBatch::ParticleBatch(size_t numParticles, float particleSize, float maxAge) : m_numParticles(numParticles) , m_particleRadius(particleSize) , m_maxAge(maxAge) , m_age(0.0) // 2d quad drawn as a triangle fan , m_data_quad({ 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f}) { //std::cout<<"[ParticleBatch] create for " << numParticles << " num particles" << std::endl; m_data_position.resize(m_numParticles); m_data_velocity.resize(m_numParticles); m_data_kind.resize(m_numParticles); m_data_max_age.resize(m_numParticles); std::string vss_particles = "../data/shader/particle.vert"; std::string fss_particles = "../data/shader/particle.frag"; m_shader.init(); m_shader.loadFile(vss_particles, GL_VERTEX_SHADER); m_shader.loadFile(fss_particles, GL_FRAGMENT_SHADER); } ParticleBatch::~ParticleBatch() { // TODO: find out if stuff must be deallocated } void ParticleBatch::setParticle(size_t index, const glm::vec2 &p, const glm::vec2 &v) { if (index >= m_numParticles) { return; } //std::cout<<"[ParticleBatch] setParticle " << index << std::endl; m_data_position[index] = p; m_data_velocity[index] = v; m_data_kind[index] = 0.0; m_data_max_age[index] = 0.0; } void ParticleBatch::bind() { //std::cout<<"[ParticleBatch] bind" << std::endl; for (size_t i=0; i<5; i++) { //std::cout<<"vbo #" << i << ": " << m_data_vbos[i] << std::endl; glEnableVertexAttribArray(i); glBindBuffer(GL_ARRAY_BUFFER, m_data_vbos[i]); if (i != 0) { glVertexAttribDivisor(i, getDivisorForIndex(i-1)); } // TODO: i or index? at first argument? glVertexAttribPointer( i, dataSizeForIndex(i), GL_FLOAT, // Data is floating point type GL_FALSE, // No fixed point scaling 0, // stride: no NULL); // No offset } } void ParticleBatch::upload() { //std::cout<<"[ParticleBatch] upload to vbo's " << std::endl; glGenBuffers(4, m_data_vbos); // Generate buffer for (size_t i=0; i<4; i++) { size_t bufferDataSize = dataSizeForIndex(i) * m_numParticles * sizeof(float); glEnableVertexAttribArray(i); glBindBuffer(GL_ARRAY_BUFFER, m_data_vbos[i]); // fill buffer with the loaded mesh position data glBufferData( GL_ARRAY_BUFFER, // Buffer target bufferDataSize, // Buffer data size dataSourceForIndex(i), // Buffer data pointer GL_STATIC_DRAW); // Usage - Data never changes; } } void ParticleBatch::render() { //std::cout<<"[ParticleBatch] render " << std::endl; m_shader.bind(); // TODO: does that work? glBindAttribLocation(m_shader.program(), 0, "in_vertex"); glBindAttribLocation(m_shader.program(), 1, "in_position"); glBindAttribLocation(m_shader.program(), 2, "in_velocity"); glUniform1f(m_shader.location("time"), m_age); glUniform1f(m_shader.location("maxAge"), m_maxAge); glUniform1f(m_shader.location("size"), m_particleRadius); bind(); //glDrawArrays(GL_TRIANGLE_FAN, 0, 4*m_numParticles); //glDrawArraysInstanced( GLenum mode, GLint first, GLsizei count, GLsizei primcount); glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, 4*m_numParticles); #if 0 glBegin(GL_QUADS); for (size_t index=0; index= m_maxAge; } }