yeah, particle rendering is working.
This commit is contained in:
parent
eb3c0f5cd4
commit
6168407973
5 changed files with 121 additions and 84 deletions
|
@ -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);
|
||||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
|
if (result == GL_FALSE) {
|
||||||
if (len > 1) {
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
|
||||||
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) {
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,20 +113,22 @@ 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("size"), m_particleRadius);
|
glUniform1f(m_shader.location("maxAge"), m_maxAge);
|
||||||
glUniform2f(m_shader.location("velocity"), m_data_velocity[0].x, m_data_velocity[0].y);
|
glUniform1f(m_shader.location("size"), m_particleRadius);
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue