Sunny_Lime

04-17-2017, 02:56 PM

So I have a scene where I'm drawing a bunch of different spheres, and each sphere is just a single solid color. I'm doing this by interleaving the color and vertex data into a single array, like { x1,y1,z1,r1,g1,b1,x2,y2... }. I'm approximating the spheres from an icosahedron, similar to this (http://stackoverflow.com/questions/7687148/drawing-sphere-in-opengl-without-using-glusphere). Unfortunately, to get decent approximations, each sphere is over 1000 vertices, which means over 1000 copies of exactly the same color. I also need to loop through each vertex in order to combine the color/vertex data into a single array, which takes way too long.

Ideally, I could just pass a single color vec3 into the shader. I can't use a uniform, because the colors will be different for each sphere. I saw this post (http://stackoverflow.com/questions/7223623/storing-different-vertex-attributes-in-different-vbos), which I'm guessing is the right direction for me. But I cannot get that solution to work at all. For one thing, glEnableVertexAttrib does not seem to be valid in my version of opengl. Any help would be much appreciated.

Here's the relevant code:

void Visual::drawVertices() {

std::vector<SimulationObject> objects = simulation.getCurrentObjects();

std::vector<float> offsets = simulation.GetFocusOffsets(objects);

for (int i = 0; i < objects.size(); i++) {

std::vector<GLfloat> vertices(2 * sphere.vertices.size());

//sphere is just a collection of vertices/indices.

//need to translate each vertex for the current object, and combine them with colors.

//This loop is KILLING the fps. Could get rid of it if I could pass a single color and vertex offset into the shader

for (int j = 0, k = 0; j < sphere.vertices.size(); j+=3, k+=6) {

vertices[k] = objects[i].position.GetBaseValue(0) - offsets[0] + sphere.vertices[j];

vertices[k + 1] = objects[i].position.GetBaseValue(1) - offsets[1] + sphere.vertices[j + 1];

vertices[k + 2] = objects[i].position.GetBaseValue(2) - offsets[2] + sphere.vertices[j + 2];

vertices[k + 3] = simulation.objectSettings[i].color[0];

vertices[k + 4] = simulation.objectSettings[i].color[1];

vertices[k + 5] = simulation.objectSettings[i].color[2];

}

glGenVertexArrays(1, &VAO);

glGenBuffers(1, &VBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);

glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), &vertices[0], GL_STREAM_DRAW);

// Position Attribute

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);

glEnableVertexAttribArray(0);

// Color attribute

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));

glEnableVertexAttribArray(1);

glGenBuffers(1, &EBO);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

glBufferData(GL_ELEMENT_ARRAY_BUFFER, sphere.indices.size() * sizeof(GLfloat), &sphere.indices[0], GL_STREAM_DRAW);

glBindVertexArray(VAO);

glDrawElements(GL_TRIANGLES, sphere.indices.size(), GL_UNSIGNED_INT, 0);

glBindVertexArray(0);

glDeleteVertexArrays(1, &VAO);

glDeleteBuffers(1, &VBO);

glDeleteBuffers(1, &EBO);

}

}

and vertex shader:

#version 330 core

layout (location = 0) in vec3 position;

layout (location = 1) in vec3 inputColor;

out vec3 vertexColor;

uniform mat4 model;

uniform mat4 view;

uniform mat4 projection;

void main()

{

gl_Position = projection * view * model * vec4(position, 1.0f);

vertexColor = inputColor;

}

Ideally, I could just pass a single color vec3 into the shader. I can't use a uniform, because the colors will be different for each sphere. I saw this post (http://stackoverflow.com/questions/7223623/storing-different-vertex-attributes-in-different-vbos), which I'm guessing is the right direction for me. But I cannot get that solution to work at all. For one thing, glEnableVertexAttrib does not seem to be valid in my version of opengl. Any help would be much appreciated.

Here's the relevant code:

void Visual::drawVertices() {

std::vector<SimulationObject> objects = simulation.getCurrentObjects();

std::vector<float> offsets = simulation.GetFocusOffsets(objects);

for (int i = 0; i < objects.size(); i++) {

std::vector<GLfloat> vertices(2 * sphere.vertices.size());

//sphere is just a collection of vertices/indices.

//need to translate each vertex for the current object, and combine them with colors.

//This loop is KILLING the fps. Could get rid of it if I could pass a single color and vertex offset into the shader

for (int j = 0, k = 0; j < sphere.vertices.size(); j+=3, k+=6) {

vertices[k] = objects[i].position.GetBaseValue(0) - offsets[0] + sphere.vertices[j];

vertices[k + 1] = objects[i].position.GetBaseValue(1) - offsets[1] + sphere.vertices[j + 1];

vertices[k + 2] = objects[i].position.GetBaseValue(2) - offsets[2] + sphere.vertices[j + 2];

vertices[k + 3] = simulation.objectSettings[i].color[0];

vertices[k + 4] = simulation.objectSettings[i].color[1];

vertices[k + 5] = simulation.objectSettings[i].color[2];

}

glGenVertexArrays(1, &VAO);

glGenBuffers(1, &VBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);

glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), &vertices[0], GL_STREAM_DRAW);

// Position Attribute

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);

glEnableVertexAttribArray(0);

// Color attribute

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));

glEnableVertexAttribArray(1);

glGenBuffers(1, &EBO);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

glBufferData(GL_ELEMENT_ARRAY_BUFFER, sphere.indices.size() * sizeof(GLfloat), &sphere.indices[0], GL_STREAM_DRAW);

glBindVertexArray(VAO);

glDrawElements(GL_TRIANGLES, sphere.indices.size(), GL_UNSIGNED_INT, 0);

glBindVertexArray(0);

glDeleteVertexArrays(1, &VAO);

glDeleteBuffers(1, &VBO);

glDeleteBuffers(1, &EBO);

}

}

and vertex shader:

#version 330 core

layout (location = 0) in vec3 position;

layout (location = 1) in vec3 inputColor;

out vec3 vertexColor;

uniform mat4 model;

uniform mat4 view;

uniform mat4 projection;

void main()

{

gl_Position = projection * view * model * vec4(position, 1.0f);

vertexColor = inputColor;

}