I am trying to render an vbo that has 7 components (interlaving right?). The first 4 are x,y,z,w (w is a scaling factor) and the remaining 3 are to be used for brigthness adjustment in the fragment shader.
This is how i create the vbo:
std::vector<float> pointCloudData;
while(endOfFile != true){
... // a lot of textfile handling/reading before, total of 100361 coordinates read.
for (int i = 0; i < 4; i++){
pointCloudData.push_back(xyzFromFile[i]); //store the read x y z w coordinate
}
// store extra data
// right now im setting everything to 1.f just to see results in fragment shader!
pointCloudData.push_back(1.f);
pointCloudData.push_back(1.f);
pointCloudData.push_back(1.f);
}
v_size = pointCloudData.size();
// create vbo
glGenVertexArrays(1, &_vaoID);
glGenBuffers(1, &_vboID);
glBindVertexArray(_vaoID);
glBindBuffer(GL_ARRAY_BUFFER, _vboID);
glBufferData(GL_ARRAY_BUFFER, v_size*sizeof(GLfloat), &pointCloudData[0], GL_DYNAMIC_DRAW);
glBindVertexArray(0);
In rendering method:
glBindVertexArray(_vaoID);
glBindBuffer(GL_ARRAY_BUFFER, _vboID);
glEnableVertexAttribArray(positionAttrib);
GLsizei stride = sizeof(GLfloat) * 7;
glVertexAttribPointer(positionAttrib, 4, GL_FLOAT, GL_FALSE, stride, (void*)0); // x y z
glVertexAttribPointer(brightnessDataAttrib, 3, GL_FLOAT, GL_FALSE, stride, (void*)(4 * sizeof(GLfloat))); // remaining data
glDrawArrays(GL_POINTS, 0, vertsToDraw);
glDisableVertexAttribArray(positionAttrib);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
Vertex shader:
layout(location = 0) in vec4 in_position;
layout(location = 2) in vec3 in_brightness;
out vec3 vs_brightness;
void main()
{
vs_brightness = in_brightness;
gl_Position = ViewProjection * vs_position;
}
Fragment shader:
in vec3 vs_brightness;
void main(void)
{
diffuse = vec4(vs_brightness[1],0,0,1); // at this point i just want SOMETHING to show up
}
If this is a bad way, how can I do it differently? How can I send the remaining 3 scalars to the fragment shader? (its a total of 3 * 100361 scalars).
This mostly looks ok. You're never enabling the second vertex attribute, though. You'll need this somewhere in your setup code:
glEnableVertexAttribArray(brightnessDataAttrib);
This assumes that positionAttrib
is 0 and brightnessDataAttrib
is 2, matching the locations in the vertex shader.
While not a correctness issue, you're not taking good advantage of the VAO. During setup, you create and bind a VAO, but then don't set up any of the state that is tracked in a VAO. Instead, you have all of that in the draw call. This defeats the purpose of using a VAO. The idea is that it holds on to all the vertex setup state, and then you can get all the necessary state for drawing by simply binding the VAO again.
So in the setup code, a better structure looks like this:
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, ...);
glBindVertexArray(vaoID);
glEnableVertexAttribArray(...);
glVertexAttribPointer(...);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
Then in the draw code, you only need this:
glBindVertexArray(vaoID);
glDrawArrays(...);
glBindVertexArray(0);
The glBindVertexArray(0)
calls aren't really necessary if you're using VAOs in all of your code, since everybody will be binding the necessary VAO before drawing. Some people like to have the explicit unbind just in case other parts of the code want to render without a VAO. But it's a waste otherwise.