Sending normalized vertex attribute produces garbage - c++

I'm trying to send a color attribute to my GLSL shader.
The colors are stored in a tightly packed byte array with 3 consecutive bytes making up an RGB triplet.
The shader expects a vec3 so I call glVertexAttribPointer to send normalized float values to the shader.
glBindBuffer(GL_ARRAY_BUFFER, attributeBuffers[COLOR]);
glBufferData(GL_ARRAY_BUFFER, mesh.n_vertices() * 3 * sizeof(GLubyte), color, GL_STATIC_DRAW);
// a little later
glEnableVertexAttribArray(attributes[COLOR]);
glBindBuffer(GL_ARRAY_BUFFER, attributeBuffers[COLOR]);
glVertexAttribPointer(attributes[COLOR], 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
What happens is that:
The colors don't seem to arrive in the shader, the vertices are colored in a single green color
The application takes a massive performance hit
When I manually normalize the color values, copy them to a float array and send that to OpenGL it renders without any problem:
glBindBuffer(GL_ARRAY_BUFFER, attributeBuffers[COLOR]);
glBufferData(GL_ARRAY_BUFFER, mesh.n_vertices() * 3 * sizeof(GLfloat), colorf, GL_STATIC_DRAW);
// a little later
glEnableVertexAttribArray(attributes[COLOR]);
glBindBuffer(GL_ARRAY_BUFFER, attributeBuffers[COLOR]);
glVertexAttribPointer(attributes[COLOR], 3, GL_FLOAT, GL_FALSE, 0, 0);
I tested this on an AMD graphics card with an OpenGL 3.0 context.
Why is this happening? Am I missing something?

As per Bahbar's suggestion I am now aligning the color triplets to 32-bits and it works flawlessly. Colors arrive correctly in the shader and there is no performance hit at all.

Related

Opengl: triangles with element buffer object (EBO) aka GL_ELEMENT_ARRAY_BUFFER

I am trying to render a kinect depth map in real time and in 3D using openGL in an efficient way to possibly scale up and use multiple kinects.
A frame from the kinect gives 640*480 3D coordinates. X and Y are static and Z vary each frame depending on the depth of what the kinect films.
I am trying to modify my GL_ARRAY_BUFFER but partially since the X and Y don't change, I just need to change the Z part of the buffer. This is easy yet, I can use glBufferSubData or glMapBuffer to partially change the buffer and I thus decided to put all X values together, all Y togethers and all Z together at the end, I can thus change in one block the whole Z values.
The problem is the following: Since I have a cloud points of vertices, I want to draw triangles from them and the easy way I found was using a GL_ELEMENT_ARRAY_BUFFER which prevents repeating vertices multiple times. But GL_ELEMENT_ARRAY_BUFFER reads from the buffer X,Y,Z in an automatic way. Like you give the indice 0 to the GL_ELEMENT_ARRAY_BUFFER, I'd like him to take his X from the first X element in the buffer, his Y from the first Y element in the buffer and his Z from the first Z element in the buffer. Since the vertices coordinates are not arranged in a continuous fashion, it doesn't work.
Is there an alternative to specify to the GL_ELEMENT_ARRAY_BUFFER how to interprete the indices?
I tried to find a way to glBufferSubData in a disparate way (not big continuous chunk of memory but rater changing an element in the buffer every 3 steps, but this seems not optimal)
I'm not entirely sure what the problem is here? Indices stored within a GL_ELEMENT_ARRAY_BUFFER can be used to index multiple buffers at the same time. Just set up your separated vertex buffers in your VAO:
glBindBuffer(GL_ARRAY_BUFFER, vbo_X);
glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, sizeof(float), 0); //< x
glBindBuffer(GL_ARRAY_BUFFER, vbo_Y);
glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, sizeof(float), 0); //< y
glBindBuffer(GL_ARRAY_BUFFER, vbo_Z);
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(float), 0); //< z
Set your indices and draw:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_vbo);
glDrawElements(GL_TRIANGLES, num_indices, GL_UNSIGNED_INT, 0);
And then just recombine the vertex data in your vertex shader
layout(location = 0) in float x_value;
layout(location = 1) in float y_value;
layout(location = 2) in float z_value;
uniform mat4 mvp;
void main() {
gl_Position = mvp * vec4(x_value, y_value, z_value, 1.0);
}

OpenGL optimize Mesh Drawing (VAO? without indices?)

Ok after some timeout I am continuing my studies about OpenGL3.2+, now I am confused about how to optimize something like this:
// Verts
glBindBuffer(GL_ARRAY_BUFFER, VertBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * size, verts, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(VERTEX_COORD_ATTRIB);
glVertexAttribPointer(VERTEX_COORD_ATTRIB,3,GL_FLOAT, GL_FALSE, sizeof(float) * floatsPerVertex, 0);
// Textures
glBindBuffer(GL_ARRAY_BUFFER, TexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * texsize, tex, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(TEXTURE_COORD_ATTRIB);
glVertexAttribPointer(TEXTURE_COORD_ATTRIB, 2, GL_FLOAT, GL_FALSE, sizeof(float) * TexCoords2D, 0);
//add light color info
glBindBuffer(GL_ARRAY_BUFFER, ColorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colorsize, lightcolor, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(COLOR_ATTRIB);
glVertexAttribPointer(COLOR_ATTRIB, 4, GL_FLOAT, GL_FALSE, sizeof(float) * ColorInfo, 0);
// Draw
glDrawArrays(GL_TRIANGLES, 0, size);
// Clean up
glDisableVertexAttribArray(VERTEX_COORD_ATTRIB);
glDisableVertexAttribArray(TEXTURE_COORD_ATTRIB);
glDisableVertexAttribArray(COLOR_ATTRIB);
Lets assume this is done for a few meshes, currently each mesh is always pushed like this, bound, buffered and drawn. Needles to say that this is surely no effective approach.
Now when reading (many) tutorials, the one thing I always see is that it is suggested to use VAO to improve that, now my difficulty to understand is- each single tutorial seems to refer in that relation also to indexed drawing. While this method seems to be perfectly fine when using an example with something extremely simple like 2 quads, I am wondering now how one is supposed to create an index for a real complex mesh? Or is it just assumed that this is available (due to .obj file or something).
Also I am confused about if a VAO always needs an index or could it be used without? And if so, would it even make sense without, since I read that an optimization makes use of knowing the index?
You see there is a lot of confusion here yet and I realize this might be a silly question again :)
However, what I want to finally achieve is, instead of pushing each mesh like this, to buffer each mesh once in the memory of the graphics card and redraw it then from the buffer.
I don't know yet a VAO is even the right approach, but every tutorial I read seems to have VAO's as the next step.
First of all you should separate your GRAM writting with glBufferData() from your drawing calls with glDrawArrays(). This significantly drops your performance, because you are basicly copying your data from RAM to GRAM on every drawing call.
For this purpose you can use VAOs:
// setting up buffers
glBindVertexArray(VertexArrayIndex);
glBindBuffer(GL_ARRAY_BUFFER, VertBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * size, verts, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(VERTEX_COORD_ATTRIB);
glVertexAttribPointer(VERTEX_COORD_ATTRIB,3,GL_FLOAT, GL_FALSE, sizeof(float) * floatsPerVertex, 0);
// Textures
glBindBuffer(GL_ARRAY_BUFFER, TexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * texsize, tex, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(TEXTURE_COORD_ATTRIB);
glVertexAttribPointer(TEXTURE_COORD_ATTRIB, 2, GL_FLOAT, GL_FALSE, sizeof(float) * TexCoords2D, 0);
//add light color info
glBindBuffer(GL_ARRAY_BUFFER, ColorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colorsize, lightcolor, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(COLOR_ATTRIB);
glVertexAttribPointer(COLOR_ATTRIB, 4, GL_FLOAT, GL_FALSE, sizeof(float) * ColorInfo, 0);
glBindVertexArray(0);
// your drawing call
glBindVertexArray(VertexArrayIndex);
glDrawArrays(GL_TRIANGLES, 0, size);
glBindVertexArray(0);
If you want to draw really big meshes (their size is bigger than GRAM available on you graphic card) you should take interest in splitting your data into small chunks. Having all that data in one big array may cause some nasty memory allocation and rendering issues (believe me - I've been there ;)).
I suggest your next step should be to turn your vertex atrributes into a struct rather than separate arrays. That way, you're only using one array object, and GPUs much prefer this memory layout.
Beyond that:
Whether you go indexed or not depends heavily on your data; it's not a requirement for fast performance, but it can help; the other option is to use triangle strips, this also reduces the amount of vertex data. If you have multiple meshes in a single array object, you can simply change your vertex attrib pointers to start at a different location in the array object in order to draw a different mesh. Then you're not switching between array objects so much.
Most of these decisions should be driven by your constraints and by performance measurements!

How to Access data on cuda by openGL?

I have generally learned OpenGL Interoperability with CUDA, but my problem is like this:
I have a lot of arrays, some for vertex, some for norm and some for alpha value alone, and some pointers to these arrays on device memory (something like dev_ver, dev_norm) which are used in kernel. I have already mapped the resource and now I want to use these data in shaders to make some effects. My rendering code is like this:
glUseProgram (programID);
glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer_0);
glBufferData(GL_ARRAY_BUFFER, size, _data_on_cpu_0, GL_DYNAMIC_DRAW);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer_1);
glBufferData(GL_ARRAY_BUFFER, size, _data_on_cpu_1, GL_DYNAMIC_DRAW);
glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer_2);
glBufferData(GL_ARRAY_BUFFER, size, _data_on_cpu_2, GL_DYNAMIC_DRAW);
glVertexAttribPointer (2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray (0);
glEnableVertexAttribArray (1);
glEnableVertexAttribArray (2);
glDrawArrays (GL_TRIANGLES, 0, _max_);
glDisableVertexAttribArray (0);
glDisableVertexAttribArray (1);
glDisableVertexAttribArray (2);
However, now I have no _data_on_cpu_, is it still possible to do the same thing ? The sample in cuda 6.0 is something like this:
glBindBuffer(GL_ARRAY_BUFFER, posVbo);
glVertexPointer(4, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, normalVbo);
glNormalPointer(GL_FLOAT, sizeof(float)*4, 0);
glEnableClientState(GL_NORMAL_ARRAY);
glColor3f(1.0, 0.0, 0.0);
glDrawArrays(GL_TRIANGLES, 0, totalVerts);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
I don't exactly understand how this could work and what to do in my case.
By the way, the method I have used is to cudaMemcpy the dev_ to host and do the render like usual, but this is obviously not efficient, because when I do rendering I again send the data back to GPU by OpenGL (if I'm right).
It's not really clear what your asking for, you mention CUDA yet none of the code you have posted is CUDA specific. I'm guessing vertexbuffer_2 contains additional per vertex information you want to access in the shader?
OpenGL calls are as efficient as you will get it, they aren't actually copying any data back from device to host. They are simply sending the addresses to the device, telling it where to get the data from and how much data to use to render.
You only need to fill the vertex and normal information at the start of your program, there isn't much reason to be changing this information during execution. You can then change data stored in texture buffers to pass additional per entity data to shaders to change model position, rotation, colour etc.
When you write your shader you must include in it;
attribute in vec3 v_data; (or similar)
When you init your shader you must then;
GLuint vs_v_data = glGetAttribLocation(p_shaderProgram, "v_data");
Then instead of your;
glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer_2);
glBufferData(GL_ARRAY_BUFFER, size, _data_on_cpu_2, GL_DYNAMIC_DRAW);
glVertexAttribPointer (2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
You use;
glEnableVertexAttribArray (vs_v_data);
glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer_2);
glBufferData(GL_ARRAY_BUFFER, size, _data_on_cpu_2, GL_DYNAMIC_DRAW);
glVertexAttribPointer (vs_v_data, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
This should let you access a float3 inside your vshaders called v_data that has whatevers stored in vertexBuffer_2, presumably secondary vertex information to lerp between for animation.
A simple shader for this that simply repositions vertices based on an input tick
#version 120
attribute in float tick;
attribute in vec3 v_data;
void main()
{
gl_Vertex.xyz = mix(gl_Vertex.xyz, v_data, tick);
}
If you want per entity data instead of/in addition to per vertex data, you should be doing that via texture buffers.
If your trying to access vertex buffer obj data inside kernels you need to use a bunch of functions;
cudaGraphicsGLRegisterBuffer() This will give you a resource pointer to the buffer, execute this once after you initially setup the vbo.
cudaGraphicsMapResources() This will map the buffer (you can use it in CUDA but not gl)
cudaGraphicsResourceGetMappedPointer() This will give you a device pointer to the buffer, pass this to the the kernel.
cudaGraphicsUnmapResources() This will unmap the buffer (you can use it in gl, but not CUDA)

OpenGL 3 VBO Indexing Multiple figures (glDrawElements)

I'm working on my first steps with OpenGL (3.x) and I plan to use VAO & VBO's to draw several figures (triangle, cube,...):
Now i got the following setup:
VAO -->
VBO [vertices, colors] + VBO [indices]
Where "vertices" has [3 * 3floats vertices of triangle, 8*3floats of cube],
"colors" has RGB per vertex (no alpha),
"indices" has [ triangle: 0,1,2, square: 0,1,2, 0,2,3, ...]
Now if I draw using "glDrawElements". i only see the first figure on the series drawn correctly (and getting the right color), the second one doesn't works as it should.
So if i render the triangle data first, it goes like:
And if i render the cube first, it goes like:
Note: triangle is red, and cube is colourful, so the first figure is always shown as I expected
This worked ok drawing arrays with "glDrawArrays" (with offset + trianglecount) instead of drawElements but, of course, indexing makes the data arrays muuuuuch smaller. So i wanted to do the move.
How could i draw the same setup but with indexing? should i call another method?
This is the code I use to prepare the VBO's data, in case of doubt.
// VBOS solid
glBindBuffer(GL_ARRAY_BUFFER, vboSolid[0]);
glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(GLfloat),&vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vboSolid[1]);
glBufferData(GL_ARRAY_BUFFER, colors.size()*sizeof(GLfloat),&colors[0], GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIndex );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLuint),&indices[0], GL_STATIC_DRAW);
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
And this is the call I do when rendering.
In this loop, the triangle would have indicesCount=3 & offset=0, while cube would have 24 & 3 respectively.
glDrawElements(
GL_TRIANGLES,
primitives[i]->indicesCount,
GL_UNSIGNED_INT,
(void*) (primitives[i]->offsetIndices*sizeof(GLuint))
);
Since i was still testing after posting, i finally made a working attempt, using:
glDrawElementsBaseVertex(
GL_TRIANGLES.
__INDICES_TO_RENDER__,
GL_UNSIGNED_INT,
(void*) (__INDICES_RENDERED___*sizeof(GLuint)),
_VERTICES_RENDERED_BEFORE_
);
where "INDICES_TO_RENDER" and "INDICES_RENDERED_" are values counting 3f, so for a cube you use 24floats as value "TO_RENDER", and 0 to "_RENDERED".
"_VERTICES_RENDERED_BEFORE_" worked being a human value of vertices rendered, so before cube is rendered, it is 0, after, it should be 8.
Kinda weird (probably i did something wrong), but it worked in my tests:
It was said at Using an offset with VBOs in OpenGL, but i tried several times till i found what to put into the call.
If an expert could verify this, i would be happier :P.

How does OpenGL know what type each vertex buffer object is?

I've just read through a tutorial about Vertex Array Objects and Vertex Buffer Objects, and I can't work out from the following code how OpenGL knows the first VBO (vertexBufferObjID[0]) represents vertex coordinates, and the second VBO (vertexBufferObjID[1]) represents colour data?
glGenBuffers(2, vertexBufferObjID);
// VBO for vertex data
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[0]);
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
// VBO for colour data
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[1]);
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), colours, GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
Edit: Thanks to Peter's answer, I found the following two lines of code which hook up each VBO with the shaders (indices 0 & 1 correlate to the VBO index):
glBindAttribLocation(programId, 0, "in_Position");
glBindAttribLocation(programId, 1, "in_Color");
It doesn't, you have to tell it which is which in the shader.
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 color;
void main()
{
/* ... */
}
glVertexAttribPointer is only meant to be used with shaders. Therefore you, as the shader writer, always know what each attribute index is supposed to do, as it maps to a certain variable in your vertex shader. You control the index to variable map with commands glBindAttribLocation or glGetAttribLocation, or from special keywords inside GLSL.
If you're just using the fixed function pipeline (default shader), then you don't want to use glVertexAttribPointer. Instead for the fixed function pipe the equivalent commands are glVertexPointer and glColorPointer, etc. Note that these are deprecated commands.
Also note that for fixed function glEnableVertexAttribArray is to be replaced with glEnableClientState.