I'm writing and OpenGL application where I have a GrassPatch class that represents patches of grass in the scene. I don't want to provide any unnecessary details, so the GrassPatch.cpp looks roughly like this:
GrassPatch::GrassPatch(GLuint density)
{
m_density = density;
generateVertices();
}
void GrassPatch::generateVertices()
{
const int quadVertexCount = 64;
GLfloat bladeWidth, bladeHeight, r;
GLfloat randomX, randomZ;
m_vertices = new GLfloat[quadVertexCount * m_density];
srand(time(NULL));
for (int i = 0; i < m_density; i++)
{
// generate 64 float values and put them into their respective indices in m_vertices
}
glGenBuffers(1, &m_VBO);
glGenVertexArrays(1, &m_VAO);
glBindVertexArray(m_VAO);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * m_density * quadVertexCount, m_vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 16 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 16 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 16 * sizeof(GLfloat), (GLvoid*)(5 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(3, 8, GL_FLOAT, GL_FALSE, 16 * sizeof(GLfloat), (GLvoid*)(8 * sizeof(GLfloat)));
glEnableVertexAttribArray(3);
glBindVertexArray(0);
}
void GrassPatch::draw()
{
glBindVertexArray(m_VAO);
glPatchParameteri(GL_PATCH_VERTICES, 4);
glDrawArrays(GL_PATCHES, 0, 4 * m_density);
glBindVertexArray(0);
}
In short, the vertex array object (VAO) for each grass patch is generated inside generatVertices. My data is tightly packed and the attributes for each vertex are at indices 0, 3, 5, 8, where each vertex is composed of 16 float's. Each grass blade consists of 4 vertices, hence quadVertexCount is set to 64. The vertex shader I use is pretty straighforward and looks like this:
#version 440 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
layout (location = 2) in vec3 centerPos;
layout (location = 3) in float randomValues[8];
out vec2 TexCoord_CS;
void main()
{
TexCoord_CS = texCoord;
gl_Position = vec4(position, 1.0f);
}
The problem here is, when I try to draw each grass blade using the draw() method, I get an access violation error. However, if I slightly change the attribute indices to 0, 4, 8, 12 and make the necessary variable type changes in the vertex shader, the problem disappears and everything renders fine.
What am I missing here, what would cause a problem like this? I've spent hours on the Internet, trying to find the reason but couldn't come up with anything yet. I'm working with Visual Studio 2015 Community Edition. The graphics card I use is NVIDIA GTX 770 and all drivers are up to date.
This is not a valid call:
glVertexAttribPointer(3, 8, GL_FLOAT, GL_FALSE, 16 * sizeof(GLfloat), (GLvoid*)(8 * sizeof(GLfloat)));
The second argument (size) needs to be 1, 2, 3, or 4. If you call glGetError(), you should see a GL_INVALID_VALUE error code from this call.
Vertex attributes can only have up to 4 components, matching a vec4 type in the shader code. If you need 8 values for an attribute, you'll have to split it into 2 attributes of 4 values each, or use uniforms instead of attributes.
layout (location = 3) in float randomValues[8];
This is not a single input value. This is an array of input values. While this is perfectly legal, it does change what this means.
In particular, it means that this input array is filled in by eight separate attributes. Yes, each one of those floats is a separate attribute, from the OpenGL side. They are assigned locations sequentially, starting with the location you specified. So the input randomValues[4] comes from attribute location 7 (3 + 4).
So your attempt to provide 8 values with one glVertexAttribPointer call will not work. Well, it was never going to work, since the number of components per attribute must be on the range [1, 4]. But it double-doesn't work, since you're not filling in the other 7.
If you want to pass these 8 elements as 8 attributes like this, you therefore need eight independent calls to glVertexAttribPointer:
for(int ix = 0; ix < 8; ++ix)
glVertexAttribPointer(3 + ix, 1, GL_FLOAT, GL_FALSE, 16 * sizeof(GLfloat), (GLvoid*)((8 + ix) * sizeof(GLfloat)));
But quite frankly, you shouldn't do that. Instead of passing 8 independent attributes, you should pass 2 vec4's:
layout (location = 3) in vec4 randomValues[2];
That way, you only need 2 attributes in your OpenGL code:
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(GLfloat), (GLvoid*)(8 * sizeof(GLfloat)));
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(GLfloat), (GLvoid*)(12 * sizeof(GLfloat)));
Related
Load to VAO function
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &modelVertexVBO);
glGenBuffers(1, &sphereTransformVBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, modelVertexVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (sphereModel->numVertices * 3), &(sphereModel->vertices[0]), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
glBindBuffer(GL_ARRAY_BUFFER, sphereTransformVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (maxSphereStorage * 4 * 4), NULL, GL_STATIC_DRAW);
glVertexAttribPointer(1, 4 * 4, GL_FLOAT, GL_FALSE, 4 * 4 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribDivisor(sphereTransformVBO, 1);
glBindVertexArray(0);
Geometry drawing function:
glBindVertexArray(VAO);
glDrawArraysInstanced(sphereModel->mode, 0, sphereModel->numVertices, sphereCount);
When I try running this code it crashes with the following crash note:
Exception thrown at 0x0000000068F4EDB4 (nvoglv64.dll) in Engine.exe: 0xC0000005: Access violation reading location 0x0000000000000000.
When I remove the second VBO it works for some reason.
glVertexAttribPointer(0, 4 * 4, GL_FLOAT, GL_FALSE, 4 * 4 * sizeof(GLfloat), NULL);
Your crash is the result of a simple copy-and-paste bug. You use attribute 0 here, which means you never called glVertexAttribPointer for attribute 1. Therefore, it uses the default attribute state, thus leading to a crash.
However, I strongly suspect that you are attempting to pass a 4x4 matrix as a single attribute. That won't work; OpenGL will give you a GL_INVALID_VALUE error if you try to set the attribute's size to be more than 4.
Matrices are treated as arrays of (column) vectors. And each vector takes up a separate attribute index. So if you want to pass a matrix, you will have to use 4 attribute indices (starting with the one provided by your shader). And each one will have to have the divisor set for it as well.
Why are you remapping the Vertex Attribute pointer to your second vbo?
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
...
glVertexAttribPointer(0, 4 * 4, GL_FLOAT, GL_FALSE, 4 * 4 * sizeof(GLfloat), NULL);
refer https://www.opengl.org/sdk/docs/man/html/glVertexAttribPointer.xhtml for more info on glVertexAttribPointer()
I am guessing your draw call
glDrawArraysInstanced(sphereModel->mode, 0, sphereModel->numVertices, sphereCount);
Note the '0' index in both cases
is exceeding the size of your second VBO and hence the error. Is this intentional that you want to remap your vertex attribute pointer to the second VBO? This overwrites the first mapping, in other words your first VBO is not being used.
I suggest using GLuint attribute1; to store the index and map accordingly to avoid such problems in future. Using numbers for attribute index directly like 0 is an easy way to make mistakes like this.
I have a piece of OpenGL code that renders meshes. I use VBOs to render them. Now, meshes consist of vertices that have the following attributes:
glm::vec3 position;
glm::vec2 uv;
glm::vec4 color;
glm::vec3 normal;
glm::vec3 tangent;
glm::vec3 binormal;
Currently, I render the vertices on per-vertex basis like this:
// Upload a vector of vertices
glBindBuffer(GL_ARRAY_BUFFER, &m_vbo);
glBufferData(GL_ARRAY_BUFFER, m_vertices.size() * sizeof(Vertex), &m_vertices[0], GL_STATIC_DRAW);
// Set the "layout" of the vertex attributes
// Binormal
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (sizeof(glm::vec3) * 3 + sizeof(glm::vec2) + sizeof(glm::vec4)));
// Tangent
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (sizeof(glm::vec3) * 2 + sizeof(glm::vec2) + sizeof(glm::vec4)));
// Normal
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (sizeof(glm::vec3) + sizeof(glm::vec2) + sizeof(glm::vec4)));
// Color
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (sizeof(glm::vec3) + sizeof(glm::vec2)));
// UV
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (sizeof(glm::vec3)));
// Position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) 0);
// Draw
glDrawElements(GL_TRIANGLES, m_indices.size(), GL_UNSIGNED_SHORT, 0);
Now, I've seen people do it a bit differently. Some upload all the vertex positions first, then the UV data, then normals and so on. To do a rough visualization of the data layout:
// P = position, U = uv, N = normal
// Per-vertex layout
PUNPUNPUNPUNPUNPUNPUNPUNPUNPUNPUNPUN
// Per-attribute layout
PPPPPPPPPPPPUUUUUUUUUUUUNNNNNNNNNNNN
Is there any difference between these two layouts? Is one or the other causing any performance issues, especially if data gets updated constantly?
The first layout you're describing is typically called "interleaved", and is mostly considered advantageous. The reasoning is that it results in more local memory access patterns, which are more cache friendly.
One good reason to use a different layout would be if some of the attributes are updated much more frequently than others. In the extreme case, where some of them are static, while others are updated frequently, it might actually be beneficial to keep the static attributes in one VBO, with GL_STATIC_DRAW usage, and use a separate buffer with GL_DYNAMIC_DRAW usage for the attributes that change frequently.
#leemes brings up another interesting case in a comment above: If you often use only a subset of the attributes for draw calls, it might also be worth grouping them differently. In that case, you could have the attributes that are always used in an interleaved layout, and keep the more rarely used ones separate.
With all that said, you will often have bigger bottlenecks in your rendering pipeline, so the difference might be difficult to measure outside targeted synthetic benchmarks. Still, I think it's mostly worth it to keep everything as streamlined as possible. Particularly since most computers/devices run on battery power these days, where you don't want to waste anything.
private int vbo;
private int ibo;
vbo = glGenBuffers();
ibo = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, Util.createFlippedBuffer(vertices), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, Util.createFlippedBuffer(indices), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
//glEnableVertexAttribArray(2);
//glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, Vertex.SIZE * 4, 12);
//glVertexAttribPointer(2, 3, GL_FLOAT, false, Vertex.SIZE * 4, 20);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
//glDisableVertexAttribArray(2);
The vertex shader code looks like
#version 330
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
out vec2 texCoord0;
uniform mat4 transform;
void main()
{
gl_Position = transform * vec4(position, 1.0);
texCoord0 = texCoord;
}
So, here is my understanding. The purpose of glVertexAttribPointer is to define the format of data in the vertex buffer object. So, in vbo it stores data as follows
buffer.put(vertices[i].getPos().getX());
buffer.put(vertices[i].getPos().getY());
buffer.put(vertices[i].getPos().getZ());
buffer.put(vertices[i].getTexCoord().getX());
buffer.put(vertices[i].getTexCoord().getY());
buffer.put(vertices[i].getNormal().getX());
buffer.put(vertices[i].getNormal().getY());
buffer.put(vertices[i].getNormal().getZ());
So, we have two glVertexAttribPointer lines because we have two variables defined in the vertex shader. So basically we are defining what these two variables point to. So, the first glVertexAttribPointer defines that the first variable "position" is a vertex with three coordinates each being float. The second glVertexAttribPointer defines the second variable "texCoord" being a pair of texture coordinates each being float. So, if my understanding is correct so far then i was assuming we first need to bind the vertex buffer object first but even after commenting out this line
glBindBuffer(GL_ARRAY_BUFFER, vbo);
it still works. I am confused. How does it know which buffer object we are talking about since there are two vbos?
#datenwolf already covered the key aspect in a comment above. To elaborate some more:
You do not have to bind GL_ARRAY_BUFFER again before the glDrawElements() call. What matters is that the buffer you want to source a given attribute from is bound when you make the glVertexAttribPointer() call for that attribute.
The best way to picture this is that when you make this call:
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
you're specifying all the state needed to tell OpenGL where to get the data for attribute 0 (first argument) from, and how to read it. Most of that state is given directly by the arguments:
it has 3 components
the components are float values
vertices are read with a stride of 20 bytes...
... and starting at byte 0 of the buffer
But there's an additional implied piece of state that is also stored away for attribute 0 when you make the call:
the data is read from the buffer currently bound to GL_ARRAY_BUFFER
In other words, the state associated with each attribute includes the id of the buffer the attribute data is sourced from. This can be the same buffer for multiple/all attributes, or it can be a different buffer for each attribute.
Note that the same is not true for GL_ELEMENT_ARRAY_BUFFER. That one needs to be bound at the time of the glDrawElements() call. While it seems somewhat inconsistent, this is necessary because there's no equivalent to glVertexAttribPointer() for the index array. The API could have been defined to have this kind of call, but... it was not. The reason is most likely that it was simply not necessary, since only one index array can be used for a draw call, while multiple vertex buffers can be used.
I am trying to use a 4x4 matrix as a vertex attribute, using this code:
Mat4 matrices[numVerts];
int mtxBoneID = glGetAttribLocation(hProgram, "aMtxBone");
glEnableVertexAttribArray(mtxBoneID + 0);
glEnableVertexAttribArray(mtxBoneID + 1);
glEnableVertexAttribArray(mtxBoneID + 2);
glEnableVertexAttribArray(mtxBoneID + 3);
glVertexAttribPointer(mtxBoneID + 0, 4, GL_FLOAT, GL_FALSE, sizeof(Mat4), ((Vec4*)matrices) + 0);
glVertexAttribPointer(mtxBoneID + 1, 4, GL_FLOAT, GL_FALSE, sizeof(Mat4), ((Vec4*)matrices) + 1);
glVertexAttribPointer(mtxBoneID + 2, 4, GL_FLOAT, GL_FALSE, sizeof(Mat4), ((Vec4*)matrices) + 2);
glVertexAttribPointer(mtxBoneID + 3, 4, GL_FLOAT, GL_FALSE, sizeof(Mat4), ((Vec4*)matrices) + 3);
// shader:
// ...
attribute mat4 aMtxBone;
// ...
But all I get on the screen is garbage.
So, my answer was deleted because of reasons unknown.
Here I go again, I'll format it differently this time.
I had the EXACT same problem as the question had/has, stuff would be drawn quite messed up. At least that's the description.
What fixed it for me was calling
glDrawElementsInstancedBaseVertex(GL_TRIANGLES,
d->drawCount,
GL_UNSIGNED_INT,
0,
p_objects.size(),
0);
To draw my stuff, just this and nothing more.
HOWEVER!
This MIGHT not be the only issue you have if your stuff is drawn incorrectly. The entire list of stuff you NEED to get correct it immense. So i'm going to put a link here, which has a great tutorial on how to draw lots of stuff. Also, you can get the source code and try it out yourself.
http://ogldev.atspace.co.uk/www/tutorial33/tutorial33.html
Sources here: http://ogldev.atspace.co.uk/ogldev-source.zip
Downvote me again and delete my answer, it's content hasn't changed at all from what it was.
Ban me from the site, your loss.
you may try something like this
in your shader use layout
layout(location=x) in mat4 <name>;
x won't be equal to glGetAttribLocation,you must maintain it by yourself.it is equal to number times you call glVertexAttribPointer.
example
layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_Color;
layout(location=2) in vec4 in_Normal;
glVertexAttribPointer(0, xxxxxxxx);
glVertexAttribPointer(1, xxxxxx);
glVertexAttribPointer(2, xxxxxx);
First you need to create VBO (glGenBuffers) for your matrix, then bind it (glBindBuffer) as current, then use
glVertexAttribPointer(mtxBoneID + 0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(mtxBoneID + 1, 4, GL_FLOAT, GL_FALSE, 0, 4);
glVertexAttribPointer(mtxBoneID + 2, 4, GL_FLOAT, GL_FALSE, 0, 8);
glVertexAttribPointer(mtxBoneID + 3, 4, GL_FLOAT, GL_FALSE, 0, 12);
instead of your glVertexAttribPointer calls.
It looks like your offsets are off. It should be
((Vec4*)matrices) + sizeOf(Vec4)*i
instead of
((Vec4*)matrices) + i
Let's say I want to upload unsigned integer and float data to the graphics card, in a single draw call. I use standard VBOs (not VAO, I'm using OpenGL 2.0), with the various vertex attribute arrays combined into the single GL_ARRAY_BUFFER, and pointed to individually using glVertexAttribPointer(...), so:
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId);
glEnableVertexAttribArray(positionAttributeId);
glEnableVertexAttribArray(myIntAttributeId);
glVertexAttribPointer(positionAttributeId, 4, GL_FLOAT, false, 0, 0);
glVertexAttribPointer(colorAttributeId, 4, GL_UNSIGNED_INT, false, 0, 128);
glClear(...);
glDraw*(...);
The problem I have here is that my buffer (ref'ed by vertexBufferId), has to be created as a FloatBuffer in LWJGL, so that it can support the attribute of type GL_FLOAT, and this would seem to preclude the use of GL_INT here (or else, the other way around - it's either one or the other since the buffer cannot be of two types).
Any ideas? How would this be handled in native C code?
This would be handled in C (in a safe way) by doing this:
GLfloat *positions = malloc(sizeof(GLfloat) * 4 * numVertices);
GLuint *colors = malloc(sizeof(GLuint) * 4 * numVertices);
//Fill in data here.
//Allocate buffer memory
glBufferData(..., (sizeof(GLfloat) + sizeof(GLuint)) * 4 * numVertices, NULL, ...);
//Upload arrays
glBufferSubData(..., 0, sizeof(GLfloat) * 4 * numVertices, positions);
glBufferSubData(..., sizeof(GLfloat) * 4 * numVertices, sizeof(GLuint) * 4 * numVertices, colors);
free(positions);
free(colors);
There are other ways of doing this in as well, which involve a lot of casting and so forth. But this code emulates what you'll have to do in LWJGL.