openGL glDrawElements with interleaved buffers - c++

Thus far i have only used glDrawArrays and would like to move over to using an index buffer and indexed triangles. I am drawing a somewhat complicated object with texture coords, normals and vertex coords. All this data is gathered into a single interleaved vertex buffer and drawn using calls similar to ( Assuming all the serup is done correctly ):
glVertexPointer( 3, GL_FLOAT, 22, (char*)m_vertexData );
glNormalPointer( GL_SHORT, 22, (char*)m_vertexData+(12) );
glTexCoordPointer( 2, GL_SHORT, 22, (char*)m_vertexData+(18) );
glDrawElements(GL_TRIANGLES, m_numTriangles, GL_UNSIGNED_SHORT, m_indexData );
Does this allow for m_indexData to also be interleaved with the indices of my normals and texture coords as well as the standard position index array? Or does it assume a single linear list of inidices that apply to the entire vertex format ( POS, NOR, TEX )? If the latter is true, how is it possible to render the same vertex with different texture coords or normals?
I guess this question could also be rephrased into: if i had 3 seperate indexed lists ( POS, NOR, TEX ) where the latter 2 cannot be rearranged to share the same index list as the first, what is the best way to render that.

You cannot have different indexes for the different lists. When you specify glArrayElement(3) then OpenGL is going to take the 3rd element of every list.
What you can do is play with the pointer you specify since essentially the place in the list which is eventually accessed is the pointer offset from the start of the list plus the index you specify. This is useful if you have a constant offset between the lists. if the lists are just a random permutation then this kind of play for every vertex is probably going to be as costy as just using plain old glVertex3fv(), glNormal3fv() and glTexCoord3fv()

I am having similar trouble attempting to do the same in Direct3D 9.0
For my OpenGL 3 implementation it was rather easy, and my source code is available online if it might help you any...
https://github.com/RobertBColton/enigma-dev/blob/master/ENIGMAsystem/SHELL/Graphics_Systems/OpenGL3/GL3model.cpp

Related

glDrawRangeElements doesn't draw the chosen range

I want to draw two cubes with a rectangle between them, so I stored vertices data into a vbo,then i created an ebo(Element Buffer Object) to avoid extra vertices(42 vs 12).
I need to draw them separately, because I want the rectangle to reflect the up cube, doing stencil test and disabling the depth mask while drawing the rectangle.
I thought I could draw the first cube with a glDrawElements call
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
then, to draw the ractangle I'm trying to use glDrawRangeElements
glDrawRangeElements(GL_TRIANGLES, 36, 41, 6, GL_UNSIGNED_INT, 0);
but it is just drawing the base of the cube.
For the last cube I am using the same draw call of the first, just inverting it in the z axis.
I think i did something wrong with glDrawRangeElements parameters, because i tried doing just one call for the first cube and then the rectangle
glDrawElements(GL_TRIANGLES, 42, GL_UNSIGNED_INT, 0);
and it works.
What's wrong with that glDrawRangeElements call?
EDIT: I solved by not using a glDrawRangeElements call but a simple glDrawArrays call, rearranging the rectangle's vertices to draw two triangles;
glDrawRangeElements doesn't do what you think it does. The functionality of glDrawRangeElements is identical to glDrawElements. The only difference is that glDrawRangeElements takes a range that acts as a hint to the implementation as to which vertices you'll be using.
See, because your indices are in an array, the driver doesn't automatically know what section of the vertex data you're using. You use glDrawRangeElements as a potential performance enhancer; it lets you tell the driver what range of vertices your draw call uses.
Nowadays, glDrawRangeElements is pointless. See, the range used to matter, because implementations used to read vertex arrays from CPU memory. So when you did a regular glDrawElements, the driver had to read your index buffer, figure out what the range of vertex data was, and then copy that data from your vertex buffers into GPU memory and then issue the draw call. The Range version allows it to skip the expensive index reading step.
That doesn't matter much anymore, since now we store vertex data in buffer objects on the GPU. So you shouldn't be using glDrawRangeElements at all.

Is there a way to create the verts/indices of a cube that can be well represented by line drawing mode as well as render correctly in triangles mode?

Attempting to switch drawing mode to GL_LINE, GL_LINE_STRIP or GL_LINE_LOOP when your cube's vertex data is constructed mainly for use with GL_TRIANGLES presents some interesting results but none that provide a good wireframe representation of the cube.
Is there a way to construct the cube's vertex and index data so that simply toggling the draw mode between GL_LINES/GL_LINE_STRIP/GL_LINE_LOOP and GL_TRIANGLES provides nice results? Or is the only way to get a good wireframe to re-create the vertices specifically for use with one of the line modes?
The most practical approach is most likely the simplest one: Use separate index arrays for line and triangle rendering. There is certainly no need to replicate the vertex attributes, but drawing entirely different primitive types with the same indices sounds highly problematic.
To implement this, you could use two different index (GL_ELEMENT_ARRAY_BUFFER) buffers. Or, more elegantly IMHO, use a single buffer, and store both sets of indices in it. Say you need triIdxCount indices for triangle rendering, and lineIdxCount for line rendering. You can then set up you index buffer with:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
(triIdxCount + lineIdxCount) * sizeof(GLushort), 0,
GL_STATIC_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,
0, triIdxCount * sizeof(GLushort), triIdxArray);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,
triIdxCount * sizeof(GLushort), lineIdxCount * sizeof(GLushort),
lineIdxArray);
Then, when you're ready to draw, set up all your state, including the index buffer binding (ideally using a VAO for all of the state setup) and then render conditionally:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
if (renderTri) {
glDrawElements(GL_TRIANGLES, triIndexCount, GL_UNSIGNED_SHORT, 0);
} else {
glDrawElements(GL_LINES, lineIdxCount, GL_UNSIGNED_SHORT,
triIndexCount * sizeof(GLushort));
}
From a memory usage point of view, having two sets of indices is a moderate amount of overhead. The actual vertex attribute data is normally much bigger than the index data, and the key point here is that the attribute data is not replicated.
If you don't strictly want to render lines, but just have a requirement for wireframe types of rendering, there are other options. There is for example an elegant approach (never implemented it myself, but it looks clever) where you only draw pixels close to the boundary of polygons, and discard the interior pixels in the fragment shader based on the distance to the polygon edge. This question (where I contributed an answer) elaborates on the approach: Wireframe shader - Issue with Barycentric coordinates when using shared vertices.

How to access Vertex Indices in Fragment Shader GLSL

I am drawing indexed GL_LINES with OpenGL. I need to access the indices in my fragment shader for both vertices. Thus I need to know the two indices my line consists of. I read about the built-in variable gl_VertexID which should not be that helpful here. As I already have stored my indices in some buffer I am trying to pass them as an attribute too.
Thus my code looks like the following:
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER,vertexBuffer);
glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,0,(void*)0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER,indexBuffer);
glVertexAttribPointer(1,2,GL_UNSIGNED_INT,GL_FALSE,0,(void*)0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,indexBuffer);
Using this seem to be the wrong way to go, right?
Furthermore I use the indices to write some information via image load store atomically. Unfortunatly fetching this image via glGetTexImage yields only zeros.
So either my index passing or my image writing/fetching seems to be wrong.
I would be glad for any help here.
For attributes that have integer types in the vertex shader, you need to use glVertexAttribIPointer() (note the additional I) instead of glVertexAttribPointer().
Since you only have one index per vertex, the second argument, which is the size, should be 1. The call will then look like this:
glVertexAttribIPointer(1, 1, GL_UNSIGNED_INT, 0, (void*)0);
What you're doing seems somewhat unusual, but I can't think of a reason why using the index array as a vertex attribute would be illegal.
I believe gl_VertexID is just a sequential id of the vertices produced by the draw command, which is not the same as the vertex index.

OpenGL avoid calling glDrawElements multiple times

I'm migrating our graphics ending from using the old fixed pipeline functions to making use of the programmable pipeline. Our simplest model is just a collection of points in space where each point can be represented by different shapes. One of these being a cube.
I'm basing my code off the cube example from the OpenGL superbible.
In this example the cubes are placed at somewhat random places whereas I will have a fixed lit of points in space. I'm wondering if there is a way to pass that list to my shader so that a cube is drawn at each point vs looping through the list and calling glDrawElements each time. Is that even worth the trouble (performance wise)?
PS we are limited to OpenGL 3.3 functionality.
Is that even worth the trouble (performance wise)?
Probably yes, but try to profile nonetheless.
What you are looking for is instanced rendering, take a look at glDrawElementsInstanced and glVertexAttribDivisor.
What you want to do is store the 8 vertices of a generic cube (centered on the origin) in one buffer, and also store the coordinates of the center of each cube in another vertex attribute buffer.
Then you can use glDrawElementsInstanced to draw N cubes taking the vertices from the first buffer, and translating them in the shader using the specific position stored in the second buffer.
Something like this:
glVertexAttribPointer( vertexPositionIndex, /** Blah .. */ );
glVertexAttribPointer( cubePositionIndex, /** Blah .. */ );
glVertexAttribDivisor( cubePositionIndex, 1 ); // Advance one vertex attribute per instance
glDrawElementsInstanced( GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices, NumberOfCubes );
In your vertex shader you need two attributes:
vec3 vertexPosition; // The coordinates of a vertex of the generic cube
vec3 cubePosition; // The coordinates of the center the specific cube being rendered
// ....
vec3 vertex = vertexPosition + cubePosition;
Obviously you can have also a buffer to store the size of each cube, or another one for the orientation, the idea remains the same.
In your example every cube uses its own model matrix per frame.
If you want to keep that you need multiple drawElements calls.
If some cubes don't move (don't need a per frame model matrix) you should combine these cubes into one VBO.

Draw rectangle from squares of different colours in Opengl

I have a beamforming program running on CUDA and i have to display the output of the beam in Opengl,I have to draw a rectangle in Opengl which is composed of an array of 24x12 small squares.I have to color each of these squares with a different color based on an output from a CUDA program doing the beamforming. I have been able to draw the reactangle using a VBO to which I pass an array containing the vertices of the squares and the color of each vertices using the following a structure. The overall summary of the problem that I am facing is that I am not able to assign the colors to each of the squares correctly. Some excerpts from the code :
struct attributes {
GLfloat coords[2]; //co-ordinates of the vertices
GLfloat color[3]; //color of the vertices
};
glGenBuffers(1, &vbo_romanis); // vbo_romanis is the VBO for drawing the frame
glBindBuffer(GL_ARRAY_BUFFER, vbo_romanis);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STREAM_DRAW);
glShadeModel (GL_SMOOTH);
glUseProgram(program);
glEnableVertexAttribArray(attribute_coord);
glEnableVertexAttribArray(attribute_color);
glBindBuffer(GL_ARRAY_BUFFER, vbo_romanis);
glVertexAttribPointer(
attribute_coord2d, // attribute
2, // number of elements per vertex, here (x,y)
GL_FLOAT, // the type of each element
GL_FALSE, // take our values as-is
sizeof(struct attributes), // next coord2 appears every 5 floats
0 // offset of first element
);
glVertexAttribPointer(
attribute_color, // attribute
3, // number of elements per vertex, here (r,g,b)
GL_FLOAT, // the type of each element
GL_FALSE, // take our values as-is
sizeof(struct attributes), // stride
(GLvoid*) offsetof(struct attributes, color) // offset
);
/* Push each element in buffer_vertices to the vertex shader */
glDrawArrays(GL_QUADS, 0, 4*NUM_SQRS);
So I am facing 2 issues when i draw the array:
the colors not appearing as I want them to. From what I have read about Opengl, the color of the vertices once assigned cannot be changed. But since all the squares share vertices among them, the colors are probably messed up. If I give the same color to all the vertices,it works fine, but not when I want to draw all squares of different colors. So, if someone can point to how I can assign a different color to each of the squares that would really helpful.
How do I update the colors of the vertices for each frame, Do i need to redraw the entire frame or is there a way to just update the colors of the vertices only.
I am completely new to OpenGL programming and any help would be much appreciated.
It is not clear what your vertex data actually is, but this:
But since all the squares share vertices among them, the colors are
probably messed up.
implies to me that you are trying to use the following data for two adjacent squares (A-F being the vertices):
A---B---C
| | |
| | |
D---E---F
However, in OpenGL, a vertex is the set of all attributes, not just the postion. What you get here is that the colors will be smoothly interpolated between the squares. So technically, you need to duplicate the vertices B and E into B1/B2 and E1/E2, with B1,E1 beeing the color of the lieft square, and B2,E2 that of the right square, but the same coordiantes.
However, for your problem, there might be a shortcut, in form of flat shading by declaring your vaertex shader outputs as flat. Vertex shader outputs (varyings) are by default interpolated across the whole primitive. However, defining them as flat will prevent the interpolation. Instead, the value from just one vertex is used for the whole primitive. OpenGL uses the conecpt of the provoking vertex to define which vertex of a primitive will be the one defining the values for such flat outputs.
The command glProvokingVertex() might be used to specify the general rules for which vertex is to be selected, you can choose between the first and the last. If you cleverly construct your vertex data, you can get a vertex to be shared for both triangles of one square that will be the provoking vertex for both, so you can define the color for each "grid cell" with just the color of one corner vertex of the cell, and do not have any need for duplicating vertices.
As a side note: you have the commang glShadeModel(GL_SMOOTH); in your code. This is deprecated and also totally useless when you use the programmable pipeline, as your comments imply. However, conceptually, this is the exact opposite of the flat shading approach I'm suggesting here.
How do I update the colors of the vertices for each frame, Do i need
to redraw the entire frame or is there a way to just update the colors
of the vertices only.
OpenGL is not a scene graph library. It does not remember which objects you have drawn in the past and does not allow changing their attributes. OpenGL is a rendering API, so if you want something different to appear on the screen, you have to tell it to draw again. If you plan on updating the colors without changing the positions of the squares itself, you might be even better off using two non-interleaved VBOs to split color and position data. That way, you can have the positions statically in one buffer, and stream only the color updates in another.