yeah, particle rendering is working.

This commit is contained in:
Andreas Ortmann 2016-09-29 00:50:14 +02:00
parent eb3c0f5cd4
commit 6168407973
5 changed files with 121 additions and 84 deletions

View file

@ -32,13 +32,15 @@ namespace endofthejedi {
glGetProgramiv(m_program, GL_LINK_STATUS, &result); glGetProgramiv(m_program, GL_LINK_STATUS, &result);
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &len); glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &len);
if (len > 1) {
char *error = (char *)malloc(len); if (result == GL_FALSE) {
std::cout<<"getting error log:" << std::endl;
char *error = (char *)malloc(len+1);
glGetProgramInfoLog(m_program, len, NULL, error); glGetProgramInfoLog(m_program, len, NULL, error);
std::string str(error); std::string str(error);
std::cout << str << std::endl; std::cout << str << std::endl;
} }
std::cout << "checked program" << std::endl; //std::cout << "checked program" << std::endl;
return (bool)result; return (bool)result;
} }
@ -48,17 +50,17 @@ namespace endofthejedi {
GLint result = 0; GLint result = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &result); glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE) {
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
if (len > 1) {
char *error = (char *)malloc(len+1); char *error = (char *)malloc(len+1);
glGetShaderInfoLog(shader, 0, &len, error); glGetShaderInfoLog(shader, len, NULL, error);
std::string str(error, error + len); std::string str(error, error + len);
std::cout << str << std::endl; std::cout << str << std::endl;
} }
std::cout << "checked shader" << std::endl; //std::cout << "checked shader" << std::endl;
return (bool)result; return result != GL_FALSE;
} }
void Shader::bind() void Shader::bind()
@ -74,6 +76,8 @@ namespace endofthejedi {
glUseProgram(m_program); glUseProgram(m_program);
} }
GLuint Shader::program() { return m_program; }
void Shader::unbind() { glUseProgram(0); } void Shader::unbind() { glUseProgram(0); }
void Shader::load(const std::string &path, GLenum shadertype) { void Shader::load(const std::string &path, GLenum shadertype) {
@ -83,15 +87,18 @@ namespace endofthejedi {
return; return;
} }
GLuint cheddar = glCreateShader(shadertype); GLuint shader = glCreateShader(shadertype);
const char *cheddardata = path.c_str();
glShaderSource(cheddar, 1, &cheddardata, NULL); const char *shaderdata = path.c_str();
glCompileShader(cheddar); glShaderSource(shader, 1, &shaderdata, NULL);
checkShader(cheddar); glCompileShader(shader);
glAttachShader(m_program, cheddar); checkShader(shader);
glAttachShader(m_program, shader);
glLinkProgram(m_program); glLinkProgram(m_program);
check(); check();
glDeleteShader(cheddar);
glDeleteShader(shader);
} }
GLuint Shader::location(const std::string &name) { GLuint Shader::location(const std::string &name) {

View file

@ -57,6 +57,7 @@ class Shader {
void unbind(); void unbind();
void load(const std::string &data, GLenum shadertype); void load(const std::string &data, GLenum shadertype);
GLuint location(const std::string &name); GLuint location(const std::string &name);
GLuint program();
}; };
} }

View file

@ -2,42 +2,64 @@
#include <iostream> #include <iostream>
// TODO: use VAO's as soon as this is working
int getDivisorForIndex(int index)
{
return (index == 0) ? 1 : 4;
}
namespace endofthejedi { namespace endofthejedi {
ParticleBatch::ParticleBatch(size_t numParticles, float particleSize) ParticleBatch::ParticleBatch(size_t numParticles, float particleSize, float maxAge)
: m_numParticles(numParticles) : m_numParticles(numParticles)
, m_particleRadius(particleSize) , m_particleRadius(particleSize)
, m_maxAge(maxAge)
// 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; std::cout<<"[ParticleBatch] create for " << numParticles << " num particles" << std::endl;
size_t s = m_numParticles*4; m_data_position.resize(m_numParticles);
m_data_velocity.resize(m_numParticles);
m_data_velocity.resize(s); m_data_kind.resize(m_numParticles);
m_data_position.resize(s); m_data_max_age.resize(m_numParticles);
m_data_kind.resize(s);
m_data_max_age.resize(s);
std::string vss_particles = std::string vss_particles =
"#version 120\n" "#version 120\n"
"varying vec3 vertex;\n" "attribute vec2 in_vertex;\n"
"attribute vec2 in_position;\n"
"attribute vec2 in_velocity;\n"
"varying vec2 vertex;\n"
"uniform float time;\n" "uniform float time;\n"
"uniform float size;\n" "uniform float size;\n"
"uniform vec2 velocity;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" vec3 p = size*gl_Vertex.xyz;\n" " vec2 p = size*in_vertex;\n"
//" vec3 p = gl_Vertex.xyz;\n" " p += time * in_velocity;\n"
" p.xy += velocity*time;\n" " p += in_position;\n"
" gl_Position = vec4(p, 1.0);\n" " gl_Position = vec4(p, 0.0, 1.0);\n"
" vertex = p;\n" " vertex = in_vertex;\n"
"}\n" "}\n"
; ;
std::string fss_particles = std::string fss_particles =
"#version 120\n" "#version 120\n"
"varying vec3 vertex;\n" "varying vec2 vertex;\n"
"uniform float maxAge;\n"
"uniform float time;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);\n" //" gl_FragColor = vec4(0.5+0.5*vertex.x, 0.5+0.5*vertex.y, 0.0, 1.0);\n"
" if (length(vertex) > 1.0) {\n"
" discard;\n"
"}\n"
" float decay = time / maxAge;\n"
" gl_FragColor = vec4(1.0/max(1.0, decay), 1.0/max(1.0, 6.0*decay), 0.0, 1.0);\n"
"}\n" "}\n"
; ;
@ -51,7 +73,7 @@ namespace endofthejedi {
// TODO: find out if stuff must be deallocated // 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) void ParticleBatch::setParticle(size_t index, const glm::vec2 &p, const glm::vec2 &v)
{ {
if (index >= m_numParticles) { if (index >= m_numParticles) {
return; return;
@ -59,35 +81,25 @@ namespace endofthejedi {
//std::cout<<"[ParticleBatch] setParticle " << index << std::endl; //std::cout<<"[ParticleBatch] setParticle " << index << std::endl;
// 4 for use as tri / quad m_data_position[index] = p;
const static glm::vec2 triangles[4] = { m_data_velocity[index] = v;
glm::vec2( 1.0f, -1.0f), m_data_kind[index] = 0.0;
glm::vec2( 1.0f, 1.0f), m_data_max_age[index] = 0.0;
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() void ParticleBatch::bind()
{ {
//std::cout<<"[ParticleBatch] bind" << std::endl; //std::cout<<"[ParticleBatch] bind" << std::endl;
for (size_t i=0; i<4; i++) { for (size_t i=0; i<5; i++) {
//std::cout<<"vbo #" << i << ": " << m_data_vbos[i] << std::endl; //std::cout<<"vbo #" << i << ": " << m_data_vbos[i] << std::endl;
glEnableVertexAttribArray(i); glEnableVertexAttribArray(i);
glBindBuffer(GL_ARRAY_BUFFER, m_data_vbos[i]); glBindBuffer(GL_ARRAY_BUFFER, m_data_vbos[i]);
if (i != 0) {
glVertexAttribDivisor(i, getDivisorForIndex(i-1));
}
// TODO: i or index? at first argument? // TODO: i or index? at first argument?
glVertexAttribPointer( glVertexAttribPointer(
i, i,
@ -101,18 +113,20 @@ namespace endofthejedi {
void ParticleBatch::upload() void ParticleBatch::upload()
{ {
std::cout<<"[ParticleBatch] upload" << std::endl; std::cout<<"[ParticleBatch] upload to vbo's " << std::endl;
glGenBuffers(4, m_data_vbos); // Generate buffer glGenBuffers(4, m_data_vbos); // Generate buffer
for (size_t i=0; i<4; i++) { for (size_t i=0; i<4; i++) {
size_t bufferDataSize = dataSizeForIndex(i) * m_numParticles * sizeof(float);
glEnableVertexAttribArray(i); glEnableVertexAttribArray(i);
glBindBuffer(GL_ARRAY_BUFFER, m_data_vbos[i]); glBindBuffer(GL_ARRAY_BUFFER, m_data_vbos[i]);
// fill buffer with the loaded mesh position data // fill buffer with the loaded mesh position data
glBufferData( glBufferData(
GL_ARRAY_BUFFER, // Buffer target GL_ARRAY_BUFFER, // Buffer target
dataSizeForIndex(i) * 4 * m_numParticles * sizeof(float), // Buffer data size bufferDataSize, // Buffer data size
dataSourceForIndex(i), // Buffer data pointer dataSourceForIndex(i), // Buffer data pointer
GL_STATIC_DRAW); // Usage - Data never changes; GL_STATIC_DRAW); // Usage - Data never changes;
} }
@ -124,16 +138,23 @@ namespace endofthejedi {
m_shader.bind(); m_shader.bind();
glBindAttribLocation(m_shader.program(), 0, "in_vertex");
glBindAttribLocation(m_shader.program(), 1, "in_position");
glBindAttribLocation(m_shader.program(), 2, "in_velocity");
static float time = 0.0f; static float time = 0.0f;
time += 1.0/50.0; time += 1.0/50.0;
glUniform1f(m_shader.location("time"), time); glUniform1f(m_shader.location("time"), time);
glUniform1f(m_shader.location("maxAge"), m_maxAge);
glUniform1f(m_shader.location("size"), m_particleRadius); glUniform1f(m_shader.location("size"), m_particleRadius);
glUniform2f(m_shader.location("velocity"), m_data_velocity[0].x, m_data_velocity[0].y);
bind(); bind();
glDrawArrays(GL_TRIANGLE_FAN, 0, 4*m_numParticles); //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 #if 0
glBegin(GL_QUADS); glBegin(GL_QUADS);
@ -154,28 +175,30 @@ namespace endofthejedi {
switch(i) { switch(i) {
case 0: case 0:
case 1: case 1:
case 2:
return 2; return 2;
case 2:
case 3: case 3:
case 4:
return 1; return 1;
default: default:
std::cerr << "bad" << std::endl; std::cerr << "bad" << std::endl;
return 0; exit(-1);
} }
} }
void *ParticleBatch::dataSourceForIndex(int i) void *ParticleBatch::dataSourceForIndex(int i)
{ {
switch(i) { switch(i) {
case 0: return (void *) m_data_position.data(); case 0: return (void *) m_data_quad.data();
case 1: return (void *) m_data_velocity.data(); case 1: return (void *) m_data_position.data();
case 2: return (void *) m_data_kind.data(); case 2: return (void *) m_data_velocity.data();
case 3: return (void *) m_data_max_age.data(); case 3: return (void *) m_data_kind.data();
case 4: return (void *) m_data_max_age.data();
default: default:
std::cerr << "bad" << std::endl; std::cerr << "bad" << std::endl;
return nullptr; exit(-1);
} }
} }
} }

View file

@ -9,14 +9,14 @@
namespace endofthejedi { namespace endofthejedi {
class ParticleBatch { class ParticleBatch {
public: public:
ParticleBatch(size_t numParticles, float particleRadius); ParticleBatch(size_t numParticles, float particleRadius, float maxAge);
// deallocate opengl stuff on destroy // deallocate opengl stuff on destroy
~ParticleBatch(); ~ParticleBatch();
size_t numParticles() const { return m_numParticles; } size_t numParticles() const { return m_numParticles; }
void setParticle(size_t index, const glm::vec2 &p, const glm::vec2 &v, float kind, float maxAge); void setParticle(size_t index, const glm::vec2 &p, const glm::vec2 &v);
void bind(); void bind();
void upload(); void upload();
@ -30,15 +30,17 @@ namespace endofthejedi {
private: private:
size_t m_numParticles; size_t m_numParticles;
GLuint m_data_vbos[4]; float m_particleRadius;
float m_maxAge;
GLuint m_data_vbos[5];
std::vector<float> m_data_quad;
std::vector<glm::vec2> m_data_position; std::vector<glm::vec2> m_data_position;
std::vector<glm::vec2> m_data_velocity; std::vector<glm::vec2> m_data_velocity;
std::vector<float> m_data_kind; std::vector<float> m_data_kind;
std::vector<float> m_data_max_age; std::vector<float> m_data_max_age;
float m_particleRadius;
Shader m_shader; Shader m_shader;
}; };
} }

View file

@ -16,19 +16,23 @@ namespace endofthejedi {
addModel("../data/mesh/small_atomic_bomb.stl", &m_missileModel); addModel("../data/mesh/small_atomic_bomb.stl", &m_missileModel);
//addModel("../data/mesh/planet_128.stl", &m_planetModel); //addModel("../data/mesh/planet_128.stl", &m_planetModel);
addModel("../data/mesh/planet_12.stl", &m_planetModel); addModel("../data/mesh/planet_12.stl", &m_planetModel);
addModel("../data/mesh/ship.stl", &m_shipModel); addModel("../data/mesh/planet_12.stl", &m_shipModel);
size_t n = 10; size_t n = 100;
m_particles = new ParticleBatch(n, 0.05, 3.0);
m_particles = new ParticleBatch(n, 0.01);
// distribute in a circle
for (size_t i=0; i<n; i++) { for (size_t i=0; i<n; i++) {
float t = 2.0 * M_PI * i / (float) n;
t += 0.2*util::randf_m1_1();
glm::vec2 v = 0.2f*glm::vec2(sin(t), cos(t));
m_particles->setParticle( m_particles->setParticle(
i, i,
glm::vec2(i/(float) n, 0.0), //glm::vec2(i/(float) n, 0.0),
glm::vec2(1.0, 1.0), glm::vec2(0.0, 0.0),
0.0, v);
0.0);
} }
m_particles->upload(); m_particles->upload();
@ -102,11 +106,11 @@ namespace endofthejedi {
// TODO :Z? // TODO :Z?
renderPlanets(); //renderPlanets();
renderShips(); //renderShips();
renderMissiles(); //renderMissiles();
//renderParticles(); renderParticles();
//glColor3f(1.0, 0.0, 0.0); //glColor3f(1.0, 0.0, 0.0);
//glBegin(GL_QUADS); //glBegin(GL_QUADS);