Bubba-3D  0.9.0
Awesome game engine!
ParticleGenerator.cpp
1 /*
2  * This file is part of Bubba-3D.
3  *
4  * Bubba-3D is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Bubba-3D is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with Bubba-3D. If not, see http://www.gnu.org/licenses/.
16  */
17 #include <ResourceManager.h>
18 #include "ParticleGenerator.h"
19 #include "constants.h"
20 #include "linmath/float3x3.h"
21 #include "Camera.h"
22 #include "Particle.h"
23 #include "ParticleConf.h"
24 
25 
26 ParticleGenerator::ParticleGenerator(Texture *texture, int amount,
27  Camera *camera, chag::float4x4 modelMatrix,
28  ParticleConf *conf)
29  : texture(texture), m_amount(amount),
30  m_camera(camera), conf(conf)
31 {
32  ResourceManager::loadShader("shaders/particle.vert", "shaders/particle.frag", "particleShader");
33  shaderProgram = ResourceManager::getShader("particleShader");
34  shaderProgram->setUniformBufferObjectBinding(UNIFORM_BUFFER_OBJECT_MATRICES_NAME, UNIFORM_BUFFER_OBJECT_MATRICES_INDEX);
35  GLfloat quad[] = { //POSITION3 TEXCOORD2
36  0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
37  1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
38  0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
39 
40  0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
41  1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
42  1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
43  };
44 
45  glGenVertexArrays(1, &m_vaob);
46  glBindVertexArray(m_vaob);
47 
48  GLuint pos_vbo;
49  glGenBuffers(1, &pos_vbo);
50  glBindBuffer(GL_ARRAY_BUFFER, pos_vbo);
51  glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
52 
53  glEnableVertexAttribArray(0);
54  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
55 
56  glEnableVertexAttribArray(1);
57  glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
58 
59  /* CLEANUP */
60  glBindVertexArray(0);
61 
62  for (int i = 0; i < amount; i++) {
63  Particle *part = new Particle(conf, modelMatrix);
64  this->m_particles.push_back(part);
65  }
66 }
67 
68 
69 ParticleGenerator::~ParticleGenerator()
70 {
71 
72 }
73 
74 void ParticleGenerator::setScaleLod(bool value) {
75  doScale = value;
76 }
77 
78 
79 
81  glDisable(GL_CULL_FACE);
82  glEnable(GL_BLEND);
83  glBlendFunc(GL_SRC_ALPHA, conf->blendFunc);
84 
85  shaderProgram->backupCurrentShaderProgram();
86  shaderProgram->use();
87 
88  texture->bind(GL_TEXTURE0);
89 
90  shaderProgram->setUniform3f("color", chag::make_vector(1.0f, 1.0f, 1.0f));
91  shaderProgram->setUniform1i("sprite", 0);
92 
93  chag::float3x3 modelMatrix3x3 = getModelMatrix3x3();
94 
95 
96  float distance = length(this->m_camera->getPosition() - this->owner->getAbsoluteLocation());
97  int maxParticles = (int)(m_amount * LOD_FACTOR / distance );
98  glBindVertexArray(m_vaob);
99 
100  std::vector<Particle*> particles = this->m_particles;
101  std::sort(particles.begin(), particles.end(), [this](Particle* p1, Particle* p2) {
102  float l1 = length(this->m_camera->getPosition() - p1->getPosition());
103  float l2 = length(this->m_camera->getPosition() - p2->getPosition());
104 
105  return l1 > l2;
106  });
107 
108  int iterations = 0;
109  for (Particle *particle : particles) {
110  if (iterations > maxParticles) { break; }
111  iterations++;
112 
113  chag::float3 scale;
114  if (particle->isAlive()) {
115  if(doScale) {
116  scale = conf->calcParticleScale() * (1.0 + distance / LINEAR_SCALE_FACTOR);
117  } else {
118  scale = chag::make_vector(1.0f, 1.0f, 1.0f);
119  }
120  chag::float4x4 modelMatrix4x4 = make_matrix(modelMatrix3x3, particle->getPosition()) * chag::make_scale<chag::float4x4>(scale);
121 
122  shaderProgram->setUniformMatrix4fv("modelMatrix", modelMatrix4x4);
123 
124  glDrawArrays(GL_TRIANGLES, 0, 6);
125  }
126  }
127 
128  /* CLEANUP */
129  glBindVertexArray(0);
130  shaderProgram->restorePreviousShaderProgram();
131  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
132  glDisable(GL_BLEND);
133 
134  glEnable(GL_CULL_FACE);
135 }
136 
138  float distance = length(m_camera->getPosition() - owner->getAbsoluteLocation());
139 
140  for (Particle *particle : m_particles) {
141  if (particle->isAlive()){
142  particle->update(dt, distance, conf);
143  }
144  else if(conf->loop(dt)){
145  particle->reset(conf, owner->getModelMatrix());
146  }
147  }
148 }
149 
150 chag::float3x3 ParticleGenerator::getModelMatrix3x3() {
151  chag::float3 u = chag::normalize(m_camera->getUp());
152  chag::float3 n = chag::normalize(m_camera->getLookAt() - m_camera->getPosition());
153  chag::float3 r = chag::normalize(chag::cross(u, n));
154 
155  chag::float3 uprim = chag::cross(n, r);
156 
157  return make_matrix(r, uprim, n);
158 }
159 
160 
161 void ParticleGenerator::setLooping(bool value) {
162  conf->setLooping(value);
163 }
virtual bool loop(float dt)=0
virtual chag::float3 calcParticleScale()=0
Definition: Camera.h:26