Tsaras
Tsaras

Reputation: 493

OpenGL color buffers per frame adding too much frame time

I have written a simple Particle class that stores positions, directions, velocities, colors etc for a particle demo. Each particle is a pyramid (4 triangles) and has a single color in all it's vertices.

Every frame I loop all the particles to find their new position etc and I need each one to render on screen with it's specific color. The way I know how to do this so far is, fill a color buffer for each of the particle's vertex colors, bind it to an attribute and send it to the shaders.

This is how I do it:

GLfloat g_color_buffer_data[3*3*4];

for (int j = 0; j < 3*4 ; j++)
    {
        g_color_buffer_data[j*3]=particles[i].color.r;
        g_color_buffer_data[j*3+1]=particles[i].color.g;
        g_color_buffer_data[j*3+2]=particles[i].color.b;
    }


    // 2nd attribute buffer : colors
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
    glVertexAttribPointer(
        1,                                // attribute. No particular reason for 1, but must match the layout in the shader.
        3,                                // size
        GL_FLOAT,                         // type
        GL_FALSE,                         // normalized?
        0,                                // stride
        (void*)0                          // array buffer offset
    );

This means I have to send a color for all 12 vertices of each particle, where I would ideally only send 1 RGB triplet to color the entire particle. The vertex shader gets a color for each vertex and sends it to the fragment shader.

Now this code inserted into my per-particle loop slows down my frames by 40 ms. Without it, I'm having a frame time of 6 ms which gets raised to 45 ms.

Questions begin:

Is there a way to send a single color per-primitive/particle to color the entire thing inside the shaders (possibly by modifying the data structure of the color buffer or something else)? Is it normal for this code to be causing such a big performance hit? Since I'm new to all of this, can you point to me which call is the one that has this massive execution time? Maybe this happens because of using 4 samples per fragment in addition to having big color buffers sent for each particle to the shaders?

note: I am testing with 512 particles. I been changing the code around for hours, but at some point earlier I think I did have a frame time of 6 ms WITH 512 particles, and something like 50 ms with 2048. I was using the same color buffer and attribute binding code that I provided above.

Upvotes: 1

Views: 269

Answers (1)

const_ref
const_ref

Reputation: 4096

Yes you could use a 3D vector(such as glm::vec3) and use the x,y,z components as the rgb values. If you use a glm::vec4 then you can also have alpha values.

You can then send this to your shader using something like in vec3 in_colours; where in_colours is the glm::vec3 in the code.

    glm::vec3 in_colours= glm::vec3(r, g, b); // Will need to do in a loop or something for each particle, or add to a std::vector and send that to shader

    glUniform3fv(glGetUniformLocation(shader_program, "in_colours"), 1, glm::value_ptr(in_colours)); 

Then in the shader you can access the x, y, z component individually if needed or as a whole.

Upvotes: 2

Related Questions