Particles are not drawn

Hi,

I wrote a code for a particle generator. It runs, but it doesn’t show anything. Here is the code:

Emitter.cpp:


#include "Emitter.h"
 
 
Emitter::Emitter(GLuint nrParticles, glm::vec3 position, GLfloat radius, char *imgName)
{
this->m_Position = position;
this->m_radius = radius;
 
for (int i = 0; i < nrParticles; i++)
{
this->particles.push_back(Particle(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), 0.0f, "blur.png"));
}
 
}
 
void Emitter::Draw(Shader &shader)
{
for (int i = 0; i < particles.size() - 1; i++)
{
particles[i].Draw(shader);
}
}
 
void Emitter::Update(GLfloat dt)
{
for (int i = 0; i <= particles.size() - 1; i++)
{
particles[i].Update(dt);
}
}
 
void Emitter::SetParticlesAttributes()
{
 
for (int i = 0; i <= particles.size() - 1; i++)
{
particles[i].setLife(10.0f); //(((rand() % 10) + 1) * 15);
particles[i].setVelocity(glm::vec3(0.0f, 2.0f, 0.0f)); //(((rand() % 10) + 1) * 2));
}
}


Particle.cpp


#include "Particle.h"
#include "Camera.h"
GLfloat vertices[] = {
0.5f,  0.5f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
-0.5f,  0.5f, 0.0f, 0.0f, 1.0f
};
 
//Camera camera(glm::vec3(0.0f, 0.0f, 10.0f));
Vbo vbo;
Ebo ebo;
 
Texture texture;
 
GLuint indices[] = {  // Note that we start from 0!
0, 1, 3,   // First Triangle
1, 2, 3    // Second Triangle
};
 
Particle::Particle(glm::vec3 position, glm::vec3 velocity, GLfloat life, GLchar *imgName)
{
this->m_Position = position;
this->m_Velocity = velocity;
this->m_Life = life;
 
this->vao.Init(1);
vbo.Init(1);
ebo.Init(1);
 
this->vao.Bind();
vbo.Bind(vertices, 20);
ebo.Bind(indices, 6);
this->vao.AttribPointer(0, 3, 5, 0);
this->vao.AttribPointer(1, 2, 5, 3);
this->vao.UnBind();
 
texture.Init(1, imgName);
 
}
 
void Particle::Draw(Shader &shader)
{
 
shader.Use();
 
glm::mat4 model;
glm::mat4 view;
glm::mat4 projection;
 
model = glm::translate(model, glm::vec3(this->m_Position));
model = glm::scale(model, glm::vec3(30.0f, 30.0f, 0.0f));
view = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
projection = glm::perspective(45.0f, (float)1600 / (float)1200, 0.1f, 100.0f);
 
GLuint modelLoc(glGetUniformLocation(shader.Program, "model"));
GLuint viewLoc(glGetUniformLocation(shader.Program, "view"));
GLuint projLoc(glGetUniformLocation(shader.Program, "projection"));
 
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
 
texture.Bind();
glUniform1i(glGetUniformLocation(shader.Program, "ourTexture"), 0);
 
this->vao.Bind();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
this->vao.UnBind();
 
}
 
void Particle::Update(GLfloat dt)
{
if (this->m_Life > 0)
{
this->m_Position += m_Velocity;
}
else
{
//m_Life -= dt;
}
}
 
void Particle::setLife(GLfloat life)
{
this->m_Life = life;
}
GLfloat Particle::getLife()
{
return this->m_Life;
}
 
void Particle::setPosition(glm::vec3 position)
{
this->m_Position = position;
}
glm::vec3 Particle::getPosition()
{
return this->m_Position;
}
 
void Particle::setVelocity(glm::vec3 velocity)
{
this->m_Velocity = velocity;
}
glm::vec3 Particle::getVelocity()
{
return this->m_Velocity;
}


And Main.cpp:


#include <iostream> 
#include <glad/glad.h>
#include<KHR\khrplatform.h>
//GLFW
#include <glfw3.h>
 
#include "Shader.h"
#include "Camera.h"
 
// GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "stb_image.h"
 
#include "Emitter.h"
 
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
 
// settings
const unsigned int SCR_WIDTH = 1600;
const unsigned int SCR_HEIGHT = 1200;
 
Emitter *e1;
 
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
 
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
 
// glad: load all OpenGL function pointers
// ---------------------------------------
 
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
 
// build and compile our shader zprogram
// ------------------------------------
Shader shader("particle.vs", "particle.frag");
e1 = new Emitter(100, glm::vec3(0.0f), 30.0f, "blur.png");
 
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
GLfloat dt = glfwGetTime();
// input
// -----
processInput(window);
e1->Update(dt);
 
// render
// ------
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
 
e1->Draw(shader);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
 
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
 
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
 
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
 
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
{
std::cout << "Space Pressed" << std::endl;
e1->SetParticlesAttributes();
}
}
 
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and 
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
}

I tried to debug it but I can’t figure it out what could be wrong. If I delete the emitter object and create a particle object it draws it.But with the emitter and many particles(even with one) it doesn’t draw anything.
Can you help me with some clues please ? :slight_smile:
Thank you very much. :stuck_out_tongue:

Maybe because of this ?

this->particles.push_back(Particle(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), 0.0f, “blur.png”));

All values are set to 0. If they refer to position and size, you’ll see nothing.
But since the code related to particles was not provided, this is just a far guess.

Hi,

Thank you for your reply.The code for the particles I posted it as well. Is Particle.cpp, the second one. Also the values from the constructor are for position, velocity, life, and image. In main I give some velocity to the particles with e1->SetParticlesAttributes(); inside the processInput() function.

I’ve made 2 projects.One for instantiated particle and one for instantiated emitter. I’ve debugged and I’ve played a little and then I saw that on the emitter project, after I insert the particle objects into the vector, the constructors are destroyed (which is normal, because are going out of scope). But the objects shouldn’t be kept with them variables and all stuff inside the vector ?

What I saw more was that with the Emitter Project, the bindings with the Vao’s, Vbo’s and Ebo’s are destroyed as well, to say like that… they don’t have the same values like in Particle Project.
For 1st particle I should have VaoID = 1, VboID = 1, EboID = 2 and for the other: VaoID = 2, VboID = 3, and Ebo = 4.

All the buffers contain the same values: 3452816845.

I tried to create a copy constructor (for the first time). I’m not sure is good how I did it. The new code is:

For Constructor:

Particle::Particle(const Particle &particle)
{
this->m_Position = particle.m_Position;
this->m_Velocity = particle.m_Velocity;
this->m_Life = particle.m_Life;
}

For creating particle objects and inserting them into the vector:

Emitter::Emitter(GLuint nrParticles, glm::vec3 position, GLfloat radius, GLchar *imgName)
{
this->m_Position = position;
this->m_radius = radius;

for (int i = 0; i < nrParticles; i++)
{
this->particles.push_back(Particle(Particle(glm::vec3(0.0f), glm::vec3(0.0f), 0.0f, imgName)));
}
}

Although I’ve made this change, still doesn’t work.

maybe you’re interested in “gpu-particles”, that allows you to simulate alot more particles that “cpu-particles”: (>1 million particles)
https://sites.google.com/site/john87connor/compute-shader/tu

therefore you need 2 programs (shaders) instaed of 1:
– the first program (shader) simulates the particles
– the second program (shader) draws the particles

to simultate particles, you use a computeshader or a vertexshader + transformfeedback
to draw them, just call glDrawArrays(GL_POINTS, 0, particlecount) with a simple color program

if you want to be able to collide the particles on some of our scene’s geometry, you can “capture” the geometry too with a transformfeedback and do a simple “triangle-line” intersection test in the shader, the complete program is described in “OpenGL Programming Guide 8th edition”

I found what was the problem. In the code is used a copy constructor(Particle). Somebody told me that the object was created, copied and destroyed during the “push_back” and the copy lives on in the vector, and is destroyed after returning. So that’s why my variables have other values.
Unfortunately John, for the moment I don’t want to go to deep. I try to do the things first in my way :stuck_out_tongue:
Anyway thank you again for your replies. :stuck_out_tongue: