#include "particle_batch.hpp" #include namespace endofthejedi { ParticleBatch::ParticleBatch(size_t numParticles, float particleSize) : m_numParticles(numParticles) , m_particleRadius(particleSize) { std::cout<<"[ParticleBatch] create for " << numParticles << " num particles" << std::endl; size_t s = m_numParticles*4; m_data_velocity.resize(s); m_data_position.resize(s); m_data_kind.resize(s); m_data_max_age.resize(s); std::string vss_particles = "#version 120\n" "varying vec3 vertex;\n" "uniform float time;\n" "uniform float size;\n" "uniform vec2 velocity;\n" "void main()\n" "{\n" " vec3 p = size*gl_Vertex.xyz;\n" //" vec3 p = gl_Vertex.xyz;\n" " p.xy += velocity*time;\n" " gl_Position = vec4(p, 1.0);\n" " vertex = p;\n" "}\n" ; std::string fss_particles = "#version 120\n" "varying vec3 vertex;\n" "void main()\n" "{\n" " gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);\n" "}\n" ; m_shader.init(); m_shader.load(vss_particles.c_str(), GL_VERTEX_SHADER); m_shader.load(fss_particles.c_str(), 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, float kind, float maxAge) { if (index >= m_numParticles) { return; } //std::cout<<"[ParticleBatch] setParticle " << index << std::endl; // 4 for use as tri / quad const static glm::vec2 triangles[4] = { glm::vec2( 1.0f, -1.0f), glm::vec2( 1.0f, 1.0f), glm::vec2(-1.0f, 1.0f), glm::vec2(-1.0f, -1.0f), }; for (size_t i=0; i<4; i++) { const size_t data_index = 4*index+i; m_data_position[data_index] = p + triangles[i]; m_data_velocity[data_index] = v; m_data_kind[data_index] = kind; m_data_max_age[data_index] = maxAge; } } void ParticleBatch::bind() { //std::cout<<"[ParticleBatch] bind" << std::endl; for (size_t i=0; i<4; i++) { //std::cout<<"vbo #" << i << ": " << m_data_vbos[i] << std::endl; glEnableVertexAttribArray(i); glBindBuffer(GL_ARRAY_BUFFER, m_data_vbos[i]); // 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" << std::endl; glGenBuffers(4, m_data_vbos); // Generate buffer for (size_t i=0; i<4; i++) { glEnableVertexAttribArray(i); glBindBuffer(GL_ARRAY_BUFFER, m_data_vbos[i]); // fill buffer with the loaded mesh position data glBufferData( GL_ARRAY_BUFFER, // Buffer target dataSizeForIndex(i) * 4 * m_numParticles * sizeof(float), // 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(); static float time = 0.0f; time += 1.0/50.0; glUniform1f(m_shader.location("time"), time); glUniform1f(m_shader.location("size"), m_particleRadius); glUniform2f(m_shader.location("velocity"), m_data_velocity[0].x, m_data_velocity[0].y); bind(); glDrawArrays(GL_TRIANGLE_FAN, 0, 4*m_numParticles); #if 0 glBegin(GL_QUADS); for (size_t index=0; index