From 6168407973772041210fdd5a67e337f39174090b Mon Sep 17 00:00:00 2001 From: Andreas Ortmann Date: Thu, 29 Sep 2016 00:50:14 +0200 Subject: [PATCH] yeah, particle rendering is working. --- game/glclasses.cpp | 37 ++--- game/glclasses.hpp | 1 + game/renderer_polygon_3d/particle_batch.cpp | 127 +++++++++++------- game/renderer_polygon_3d/particle_batch.hpp | 12 +- .../renderer_polygon_3d.cpp | 28 ++-- 5 files changed, 121 insertions(+), 84 deletions(-) diff --git a/game/glclasses.cpp b/game/glclasses.cpp index ecdcd8b..dcb1d00 100644 --- a/game/glclasses.cpp +++ b/game/glclasses.cpp @@ -32,13 +32,15 @@ namespace endofthejedi { glGetProgramiv(m_program, GL_LINK_STATUS, &result); 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); std::string str(error); std::cout << str << std::endl; } - std::cout << "checked program" << std::endl; + //std::cout << "checked program" << std::endl; return (bool)result; } @@ -48,17 +50,17 @@ namespace endofthejedi { GLint result = 0; glGetShaderiv(shader, GL_COMPILE_STATUS, &result); - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); - if (len > 1) { + if (result == GL_FALSE) { + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); char *error = (char *)malloc(len+1); - glGetShaderInfoLog(shader, 0, &len, error); + glGetShaderInfoLog(shader, len, NULL, error); std::string str(error, error + len); 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() @@ -74,6 +76,8 @@ namespace endofthejedi { glUseProgram(m_program); } + GLuint Shader::program() { return m_program; } + void Shader::unbind() { glUseProgram(0); } void Shader::load(const std::string &path, GLenum shadertype) { @@ -83,15 +87,18 @@ namespace endofthejedi { return; } - GLuint cheddar = glCreateShader(shadertype); - const char *cheddardata = path.c_str(); - glShaderSource(cheddar, 1, &cheddardata, NULL); - glCompileShader(cheddar); - checkShader(cheddar); - glAttachShader(m_program, cheddar); + GLuint shader = glCreateShader(shadertype); + + const char *shaderdata = path.c_str(); + glShaderSource(shader, 1, &shaderdata, NULL); + glCompileShader(shader); + checkShader(shader); + + glAttachShader(m_program, shader); glLinkProgram(m_program); check(); - glDeleteShader(cheddar); + + glDeleteShader(shader); } GLuint Shader::location(const std::string &name) { diff --git a/game/glclasses.hpp b/game/glclasses.hpp index 9f9d693..32bed2e 100644 --- a/game/glclasses.hpp +++ b/game/glclasses.hpp @@ -57,6 +57,7 @@ class Shader { void unbind(); void load(const std::string &data, GLenum shadertype); GLuint location(const std::string &name); + GLuint program(); }; } diff --git a/game/renderer_polygon_3d/particle_batch.cpp b/game/renderer_polygon_3d/particle_batch.cpp index 7d0a59d..3582aea 100644 --- a/game/renderer_polygon_3d/particle_batch.cpp +++ b/game/renderer_polygon_3d/particle_batch.cpp @@ -2,42 +2,64 @@ #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) + ParticleBatch::ParticleBatch(size_t numParticles, float particleSize, float maxAge) : m_numParticles(numParticles) , 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; - 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); + 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 = "#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 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" + " vec2 p = size*in_vertex;\n" + " p += time * in_velocity;\n" + " p += in_position;\n" + " gl_Position = vec4(p, 0.0, 1.0);\n" + " vertex = in_vertex;\n" "}\n" ; std::string fss_particles = "#version 120\n" - "varying vec3 vertex;\n" + "varying vec2 vertex;\n" + "uniform float maxAge;\n" + "uniform float time;\n" "void main()\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" ; @@ -51,7 +73,7 @@ namespace endofthejedi { // 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) { return; @@ -59,35 +81,25 @@ namespace endofthejedi { //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; - } + 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<4; i++) { + 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, @@ -101,20 +113,22 @@ namespace endofthejedi { 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 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 - dataSizeForIndex(i) * 4 * m_numParticles * sizeof(float), // Buffer data size - dataSourceForIndex(i), // Buffer data pointer - GL_STATIC_DRAW); // Usage - Data never changes; + GL_ARRAY_BUFFER, // Buffer target + bufferDataSize, // Buffer data size + dataSourceForIndex(i), // Buffer data pointer + GL_STATIC_DRAW); // Usage - Data never changes; } } @@ -124,16 +138,23 @@ namespace endofthejedi { 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; 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); + glUniform1f(m_shader.location("time"), time); + glUniform1f(m_shader.location("maxAge"), m_maxAge); + glUniform1f(m_shader.location("size"), m_particleRadius); 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 glBegin(GL_QUADS); @@ -154,28 +175,30 @@ namespace endofthejedi { switch(i) { case 0: case 1: + case 2: return 2; - case 2: case 3: + case 4: return 1; default: std::cerr << "bad" << std::endl; - return 0; + exit(-1); } } 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(); + case 0: return (void *) m_data_quad.data(); + case 1: return (void *) m_data_position.data(); + case 2: return (void *) m_data_velocity.data(); + case 3: return (void *) m_data_kind.data(); + case 4: return (void *) m_data_max_age.data(); default: std::cerr << "bad" << std::endl; - return nullptr; + exit(-1); } } } diff --git a/game/renderer_polygon_3d/particle_batch.hpp b/game/renderer_polygon_3d/particle_batch.hpp index 1e0a26f..59d971f 100644 --- a/game/renderer_polygon_3d/particle_batch.hpp +++ b/game/renderer_polygon_3d/particle_batch.hpp @@ -9,14 +9,14 @@ namespace endofthejedi { class ParticleBatch { public: - ParticleBatch(size_t numParticles, float particleRadius); + ParticleBatch(size_t numParticles, float particleRadius, float maxAge); // deallocate opengl stuff on destroy ~ParticleBatch(); 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 upload(); @@ -30,15 +30,17 @@ namespace endofthejedi { private: size_t m_numParticles; - GLuint m_data_vbos[4]; + float m_particleRadius; + float m_maxAge; + GLuint m_data_vbos[5]; + + std::vector m_data_quad; std::vector m_data_position; std::vector m_data_velocity; std::vector m_data_kind; std::vector m_data_max_age; - float m_particleRadius; - Shader m_shader; }; } diff --git a/game/renderer_polygon_3d/renderer_polygon_3d.cpp b/game/renderer_polygon_3d/renderer_polygon_3d.cpp index 9b63feb..675ea55 100644 --- a/game/renderer_polygon_3d/renderer_polygon_3d.cpp +++ b/game/renderer_polygon_3d/renderer_polygon_3d.cpp @@ -16,19 +16,23 @@ namespace endofthejedi { addModel("../data/mesh/small_atomic_bomb.stl", &m_missileModel); //addModel("../data/mesh/planet_128.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; - - m_particles = new ParticleBatch(n, 0.01); + size_t n = 100; + m_particles = new ParticleBatch(n, 0.05, 3.0); + // distribute in a circle for (size_t i=0; isetParticle( i, - glm::vec2(i/(float) n, 0.0), - glm::vec2(1.0, 1.0), - 0.0, - 0.0); + //glm::vec2(i/(float) n, 0.0), + glm::vec2(0.0, 0.0), + v); } m_particles->upload(); @@ -102,11 +106,11 @@ namespace endofthejedi { // TODO :Z? - renderPlanets(); - renderShips(); - renderMissiles(); + //renderPlanets(); + //renderShips(); + //renderMissiles(); - //renderParticles(); + renderParticles(); //glColor3f(1.0, 0.0, 0.0); //glBegin(GL_QUADS);