182 lines
5.3 KiB
C++
182 lines
5.3 KiB
C++
|
#include "particle_batch.hpp"
|
||
|
|
||
|
#include <iostream>
|
||
|
|
||
|
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<m_numParticles; index++) {
|
||
|
for (int i=0; i<4; i++) {
|
||
|
glm::vec2 p = m_data_position[index] + triangles[i];
|
||
|
//glColor3f(1.0, 0.0, 0.0);
|
||
|
glVertex2f(p.x, p.y);
|
||
|
}
|
||
|
}
|
||
|
glEnd();
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
size_t ParticleBatch::dataSizeForIndex(int i)
|
||
|
{
|
||
|
switch(i) {
|
||
|
case 0:
|
||
|
case 1:
|
||
|
return 2;
|
||
|
|
||
|
case 2:
|
||
|
case 3:
|
||
|
return 1;
|
||
|
|
||
|
default:
|
||
|
std::cerr << "bad" << std::endl;
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void *ParticleBatch::dataSourceForIndex(int i)
|
||
|
{
|
||
|
switch(i) {
|
||
|
case 0: return (void *) m_data_position.data();
|
||
|
case 1: return (void *) m_data_velocity.data();
|
||
|
case 2: return (void *) m_data_kind.data();
|
||
|
case 3: return (void *) m_data_max_age.data();
|
||
|
default:
|
||
|
std::cerr << "bad" << std::endl;
|
||
|
return nullptr;
|
||
|
}
|
||
|
}
|
||
|
}
|