Allocating vertex buffer object - c++

I'm trying to create terrain from a heightmap in opengl(c++), and following this tutorial.
I'm also trying to use a vertex buffer object to speed it up. In their example, they create a vertex object with 3 floats for x, y, z. They then pass a pointer to an array of these vertex objects to be copied to the buffer object. What I don't understand is why for the size of the buffer parameter they pass it the size of the 3 floats (multiplied by the number of vertices).
Surely the vertex objects being passed to it are larger than just the size of the 3 floats? Does the glBufferDataARB function somehow extract these variables? Is the size of an object equal to the size of the variables in it? or am I missing something?

VBOs store bytes. Later gl*Pointer() and/or glVertexAttrib() calls tell OpenGL how to interpret those bytes.
To store three floats you need sizeof(float) * 3 bytes.
To store N three-float vertices you need sizeof(float) * 3 * N bytes.

Related

Cannot calculate number of verticies a model has. (Size of indeterminate array)

I believe my issue is because I am comparing the size of a pointer to the size of a float, instead of comparing the number of elements in the array against a float.
Model::Model(float* p_pos)
{
// Determine vertex count
m_vertexCount = (sizeof(p_pos) / sizeof(float)) / 3;
If I pass not as float* p_pos, but instead float p_pos[] nothing changes. How do I determine the number of verts in a model?
C arrays decay to pointers when passed as a function argument, so you cannot extract the length. If you want to know the length when passed to the function, you have 3 choices:
Switch to std::array
Pass the length of the array along with the array
Switch to std::vector

OpenGL - add vertices

I have a subfunction that reads a data stream and creates an array of vertex data based on that. The main function calls this subfunction repeatedly and updates the vertex data array, which is then bound to a buffer and drawn. So far, so good. However, I cannot figure out how to add vertices. C++ does not let you reassign or resize entire arrays. I can't use vectors because the OpenGL functions take in arrays, not vectors.
You can use vectors to populate an OpenGL vertex buffer. The values in a vector are guaranteed to be contiguous. See for example these discussions for details on the related language standards:
Are std::vector elements guaranteed to be contiguous?
Is it safe to assume that STL vector storage is always contiguous?
This means that code like the following is safe:
std::vector<GLfloat> vertexPositions;
// Populate vector with vertex positions.
GLuint bufId = 0;
glGenBuffers(1, &bufId);
glBindBuffer(GL_ARRAY_BUFFER, bufId);
glBufferData(GL_ARRAY_BUFFER, vertexPositions.size() * sizeof(GLfloat),
&vertexPositions[0], GL_STATIC_DRAW);
The subtle but critical part is that you pass in the address of the first element of the vector, not the address of the vector object.
I would make a slight edit. While you can use &vertexPositions[0] as the address of the beginning of an STL vector, I prefer to use the function designed to return the address of the beginning of the vector memory, vertexPositions.data().
std::vector<GLfloat> vertexPositions;
// Populate vector with vertex positions.
GLuint bufId = 0;
glGenBuffers(1, &bufId);
glBindBuffer(GL_ARRAY_BUFFER, bufId);
glBufferData(GL_ARRAY_BUFFER, vertexPositions.size() * sizeof(GLfloat), vertexPositions.data(), GL_STATIC_DRAW);
I use STL vectors for OGL data for a number of reasons. It's easy to preallocate if you know the size, and they will grow (and stay contiguous) when you add items. They are easy to iterate through. You can easily create vectors of structures if you want to pass in interleaved data. It all works the same.

difference between SSBO and Image load/store

What are the diffences between "Shader Storage Buffer Objects" (SSBO) and Image load store operations
When should one be used and not the other?
They both can have atomic operations and I assume they are stored in the same type of memory. And regardless if they are stored in the same type of memory, do they have the same performance characteristics?
edit: the original question was asking between SSBOs and Uniform buffer objects, it was meant to be between SSBO and Image load store.
The difference between shader storage buffer objects and image textures and why one would want to use them is that they can use interface blocks.
Images are just textures which mean only vec4's are in the data structure. Well not only vec4, it could have other formats, but the data structure would be many of one data type.
Where as, SSBO's are generic. They can use combinations of int's, float's, arrays of vec3's all in a single interface block.
So, SSBO's are much more flexible than just Image Texture's.
Your question is already answered more or less definitively at http://www.opengl.org/wiki/Shader_Storage_Buffer_Object. It says:
SSBOs are a lot like Uniform Buffer Objects. Shader storage blocks are
defined by Interface Block (GLSL)s in almost the same way as uniform
blocks. Buffer objects that store SSBOs are bound to SSBO binding
points, just as buffer objects for uniforms are bound to UBO binding
points. And so forth.
The major differences between them are:
SSBOs can be much larger. The smallest required UBO size is 16KB; the smallest required SSBO size is 16MB, and typical sizes will
be on the order of the size of GPU memory.
SSBOs are writable, even atomically; UBOs are uniform​s. SSBOs reads and writes use incoherent memory accesses, so they need the
appropriate barriers, just as Image Load Store operations.
SSBOs can have unbounded storage, up to the buffer range bound; UBOs must have a specific, fixed storage size. This means that you can
have an array of arbitrary length in an SSBO. The actual size of the
array, based on the range of the buffer bound, can be queried at
runtime in the shader using the length​ function on the unbounded
array variable.
As others have mentioned, SSBOs have much larger storage and supports atomic operations, the accepted answer also mentioned that SSBOs are generic in the sense that they allow users to combine different types. But personally, I just want to point out that I think this is usually BAD, it is not always ideal to use interface blocks or structs in SSBO. Here's an example:
Let's say you have a struct in C++ like this:
struct Foo {
glm::vec4 position;
glm::vec4 velocity;
glm::vec4 padding_and_range; // range is a float padded to a vec4
};
which corresponds to an SSBO buffer in glsl:
struct Foo {
vec4 position;
vec4 velocity;
vec4 padding_and_range; // range is a float padded to a vec4
};
layout(std430, binding = 0) readonly buffer SSBO {
Foo data[];
} foo;
Although the SSBO buffer is able to hold an array of struct Foo, notice that paddings must be taken into account as per the std430 memory layout, you have to padded your float range to a vec4, and then use foo.data[i].padding_and_range.w to access it. This is error-prone, let alone the waste of memory spaces, especially when your SSBO is large (to be used in a compute shader) and your Foo struct is complex (needs a lot of paddings). Apart from that, you often need to fill in the buffer data in a loop like this:
Foo* foos = reinterpret_cast<Foo*>(glMapNamedBufferRange(ssbo, offset, size, GL_MAP_READ_BIT));
for (int i = 0; i < n_foos; i++) {
Foo& foo = foos[i];
foo.position = glm::vec4(1.0f);
foo.velocity = glm::vec4(2.0f);
foo.padding_and_range = glm::vec4(glm::vec3(0.0f), 3.5f);
}
glUnmapNamedBuffer(ssbo);
instead of simply writing data to it in one go using glNamedBufferData or glNamedBufferSubData.
A better way of handling struct is to store each struct element into a separate SSBO, so that each SSBO buffer array is tightly packed and homogeneous. Even though the performance may not be any better, it helps keep your code clean and more readable. Rarher than using the struct, you would want to use:
layout(std430, binding = 0) buffer FooPosition {
vec4 position[];
};
layout(std430, binding = 1) buffer FooVelocity {
vec4 velocity[];
};
layout(std430, binding = 2) buffer FooRange {
float range[];
};

Drawing Multiple Models with glDrawArrays

I have a struct to store vertex data for 2 distinct models one is a cube the other a pyramid.
struct Model{
GLuint vboID;
GLfloat* vbo;
GLuint vaoID;
GLfloat* vao;
GLuint vertexStart;
GLuint vertexCount;
};
I create the vbos and generate their buffers like this:
Model cubeModel;
Model pyramidModel;
cubeModel.vbo = cubeVerts; //A GLfloat array I created earlier in code earlier.
cubeModel.vertexCount= sizeof(cubeVerts);//size of the GLfloat array in bytes
pyramidModel.vbo = pyVerts;
pyramidModel.vertexCount= sizeof(pyVerts);
glGenBuffers(1, &cubeModel.vboID); //Generate a buffer for the vertices
glBindBuffer(GL_ARRAY_BUFFER, cubeModel.vboID); //Bind the vertex buffer
glBufferData(GL_ARRAY_BUFFER, cubeModel.vertexCount, cubeModel.vbo, GL_STATIC_DRAW);
And then to draw I use:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, cubeModel.vertexCount);
glDisableClientState(GL_VERTEX_ARRAY);
Which works, and I successfully draw the cube, But i've been trying multiple ways to draw the pyramid as well.
What do I need to do to render both on screen at the same time?
EDIT: Here's what i've tried specifically, duplicating the glBufferData() call and passing in the pyramid data then making glDrawArays(GL_TRIANGLES,0,cubeModel.drawcount+pyramidModel.drawCount) figuring the vertex data would stack and glDrawArrays would go through all the geometry passed in one go.
I've also tried making 2 sets of instructions from glGenBuffers() to glDisableClientState() but instead using all of pyramid model's data. This was interesting because my glDrawArrays was:
glDrawArrays(GL_TRIANGLES, 0, cubeModel.drawCount);
glTranslatef(4.0f,0.0f,0.0f);
glDrawArrays(GL_TRIANGLES, 0, pyramidModel.drawCount);
and it ended up drawing a really messed up pyramid 2 times, leading me to believe that when I cal glBufferData() twice the second time Overwrites the data previously passed.
EDIT 2:After Reading Andon's comment I edited some of my code to clarify things, drawCount is now vertexCount, and m_vertexBuffer is now correctly referencing the handle I stored in cubeModel, cubeModel.vboID, instead of using an old class variable I was using to store the handle.
I do not want to muddy up the comments section, because there are a lot of things wrong with your code. But I also do not have time to go through all of them right now, so this is a sort of temporary answer.
glBufferData (...) does not technically overwrite previously passed data, it does something far worse. Every time you call glBufferData (...) it creates a new data store of the size you pass and (optionally) fills it with the data you supply (if you pass something non-NULL). Think of it more like calling free (...) and then malloc (...) or delete [] ... and new Type [...].
glBufferSubData (...) is the preferred technique for appending vertices to a vertex buffer. Unfortunately it does not resize the data store. Sometimes it is handy to over-allocate your VBO and defer supplying it data until later on (using glBufferSubData).
If you use one VBO to store both of your models, you need to know the starting vertex and the vertex count for each model as it relates to your VBO's data. Right now all you know is the number of vertices (and you have it named strangely drawCount instead of vertexCount). To most people, drawCount indicates the number of times you want to draw something, rather than the number of vertices or elements it contains.
The size field of a call to glBufferData (...) is supposed to be the size in bytes of your vertex data. Right now you're passing the number of vertices. More than likely you meant to use sizeof (YourVertexDataStructure) for the size of an individual vertex (sizeof (float [3]) in this case), and something like sizeof (cubeVerts) / sizeof (YourVertexDataStructure) to calculate the number of vertices actually stored in this array. Then the size you pass to glBufferData (...) would be: _size * count_

Dynamic VBO in OpenGL

What is the best way to store dynamic data for use in VBO (or vertex arrays). Only examples I saw were 2D static arrays and the pointer to that array was used with next parameters as stride, bytes used for one element etc. I can use "dynamic" arrays so I can specify it's size on-air, but just once. My point is that if you, for example, already drawing 1000 points (talking about 2D so I think point is better then vertex) as line strip and you add new point, this way you have to make new array with size of 1001, copy everything from old to new field, add new point and send it down to graphic's memory. Best way is to use vectors or deques as temporary storage, but then I have to convert to array and again send it down.
So is there better way to do this? Can I only add new part to VBO without sending down the old data? Or better way to store data/using vector as data source without conversion?
I usually just use the 'ole vector trick:
struct GL_Vertex
{
Eigen::Vector2f tex;
Eigen::Vector3f color;
Eigen::Vector3f pos;
};
...
vector<GL_Vertex> buf(1000);
...
glTexCoordPointer( 2, GL_FLOAT, sizeof(GL_Vertex), &buf[0].tex );
glColorPointer( 3, GL_FLOAT, sizeof(GL_Vertex), &buf[0].color );
glVertexPointer( 3, GL_FLOAT, sizeof(GL_Vertex), &buf[0].pos );