How to use a 4x4 matrix as a vertex attribute in GLSL? - c++

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

Related

glDrawArrays with cocos2d not drawing at all

I have a lot of points that i need to draw in a batch and i have been trying it for two days and i cant seem get any progress with glDrawArrays. I have tried DrawNode and drawing each individual point for testing and it works correctly... but i cant seem to get glDrawArray to give any visual result.
Here is my drawing code(changed a few variable names):
auto glProgram = getGLProgram();
if (glProgram == nullptr) {
setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(
GLProgram::SHADER_NAME_POSITION_COLOR));
glProgram = getGLProgram();
if (glProgram == nullptr) {
return;
}
}
glProgram->use();
glProgram->setUniformsForBuiltins();
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_COLOR);
GLfloat *vertices = new GLfloat[myStruct->data.size()*2];
GLfloat *colors = new GLfloat[myStruct->data.size()*4];
int vIndex = 0;
int cIndex = 0;
for (std::vector<myPointStruct*>::iterator it = myStruct->data.begin(); it != myStruct->data.end(); ++it) {
vertices[vIndex++] = (*it)->pos.x;
vertices[vIndex++] = (*it)->pos.y;
colors[cIndex++] = (*it)->color.r;
colors[cIndex++] = (*it)->color.g;
colors[cIndex++] = (*it)->color.b;
colors[cIndex++] = (*it)->color.a;
glLineWidth(10);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat), &vertices[0]);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat), &colors[0]);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDrawArrays(GL_POINTS, 0, (GLsizei) myStruct->data.size());
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, (GLsizei) myStruct->data.size());
And here is how i call the method:
_renderTexture->begin();
myMethodForDrawing();
_renderTexture->end();
Director::getInstance()->getRenderer()->render();
I have also tried:
_renderTexture->begin();
_customCommand.init(_renderTexture->getGlobalZOrder());
_customCommand.func = CC_CALLBACK_0(MyClass:: myMethodForDrawing,this);
auto renderer = Director::getInstance()->getRenderer();
renderer->addCommand(&_customCommand);
_renderTexture->end();
The 5th paramter of glVertexAttribPointer specifies the byte offset between consecutive generic vertex attributes. If stride is 0, the generic vertex attributes are understood to be tightly packed in the array.
Since your vertices and colors are tightly packed, you do not need to set the stride parameter. Note, sizeof(GLfloat) is wrong anyway. In you case it would be 2 * sizeof(GLfloat) for vertices and 4 * sizeof(GLfloat) for colors.
Change your code like this (focus on the 0 for the 5th parameter):
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, &vertices[0]);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_FLOAT, GL_FALSE, 0, &colors[0]);

Access violation error when calling glDrawArrays

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)));

Incorrect instanced rendering

Previously, to render a bunch of quads, I was simply using a few uniforms (One for a model matrix and another for the texture layer ID), however, I'd rather not have to loop through each quad and set both uniforms each time, each frame.
So I went ahead and looked for better alternatives with which I could render everything with a single call.
Now I'm using instanced rendering:
// In VAO definition
glGenBuffers(1, &instanceVBO);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), nullptr);
glVertexAttribDivisor(3, 1);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), (GLvoid*)(sizeof(glm::vec4)));
glVertexAttribDivisor(4, 1);
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), (GLvoid*)(sizeof(glm::vec4) * 2));
glVertexAttribDivisor(5, 1);
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), (GLvoid*)(sizeof(glm::vec4) * 3));
glVertexAttribDivisor(6, 1);
glEnableVertexAttribArray(7);
glVertexAttribIPointer(7, 1, GL_UNSIGNED_INT, sizeof(RenderingData), (GLvoid*)(sizeof(glm::mat4)));
glVertexAttribDivisor(7, 1);
// In quad adding function
instanceData.push_back(quad->data);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(RenderingData) * quads.size(), &instanceData[0], GL_DYNAMIC_DRAW);
// Rendering
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, quads.size());
I'm using 2 VBOs: one for per-vertex data (Position, normal, etc vectors) and another for per-instance data (Model matrix and texture layer ID).
My problem is the following: http://imgur.com/20Wb9pQ
As you can see, the middle and bottom images aren't rendering correctly (Middle one is way too stretched, whereas bottom one's UV are incorrect, since they aren't filling the whole quad), however, I'm 98% sure both my vertex and instance data are correct, since when I was using the previously mentioned uniforms, they were rendering correctly.
Also, I might 've spotted the problem: the indices. Somehow, if I change my glDrawElementsInstanced's count value to say, 12 indices, the middle one renders correctly, whereas the other 2, do not (Proof: http://imgur.com/PDQqbuT), same thing happens if I change them to 18 (The last one renders correctly and the other 2, do not).
What might the problem be?

I can't get a simple indexed array rendered properly

I am porting this sample (site) to jogl but I noticed something wasn't perfect in the image, some artefacts on the floor and shapes not exactly squared, as you can see (dont care about color, is varying), also the floor doesnt look good:
Therefore I tried to render only the floor first (if you wanna try, pretty easy, swith SQRT_BUILDING_COUNT from 100 -> 0) and there I have already the first problems, it is supposed to be a square based on two triangles, but I see only one of them.
My vertex structure:
public float[] position = new float[3];
public byte[] color = new byte[4];
public float[] attrib0 = new float[4];
public float[] attrib1 = new float[4];
public float[] attrib2 = new float[4];
public float[] attrib3 = new float[4];
public float[] attrib4 = new float[4];
public float[] attrib5 = new float[4];
public float[] attrib6 = new float[4];
attrib0-6 are unused at the moment
My VS inputs:
// Input attributes
layout(location=0) in vec4 iPos;
layout(location=1) in vec4 iColor;
layout(location=2) in PerMeshUniforms* bindlessPerMeshUniformsPtr;
layout(location=3) in vec4 iAttrib3;
layout(location=4) in vec4 iAttrib4;
layout(location=5) in vec4 iAttrib5;
layout(location=6) in vec4 iAttrib6;
layout(location=7) in vec4 iAttrib7;
I am declaring iPos as vec3, so I guess it will padded as vec4(iPos, 1) in the VS
I transfer data to gpu:
gl4.glNamedBufferData(vertexBuffer[0], Vertex.size() * vertices.size(),
GLBuffers.newDirectFloatBuffer(verticesArray), GL4.GL_STATIC_DRAW);
gl4.glNamedBufferData(indexBuffer[0], GLBuffers.SIZEOF_SHORT * indices.size(),
GLBuffers.newDirectShortBuffer(indicesArray), GL4.GL_STATIC_DRAW);
Then before I render I call:
gl4.glEnableVertexArrayAttrib(0, 0);
gl4.glEnableVertexArrayAttrib(0, 1);
Then render, original code is:
// Set up attribute 0 for the position (3 floats)
glVertexArrayVertexAttribOffsetEXT(0, m_vertexBuffer, 0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), Vertex::PositionOffset);
// Set up attribute 1 for the color (4 unsigned bytes)
glVertexArrayVertexAttribOffsetEXT(0, m_vertexBuffer, 1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), Vertex::ColorOffset);
I substituted it with:
// Set up attribute 0 for the position (3 floats)
gl4.glVertexArrayVertexBuffer(0, 0, vertexBuffer[0], Vertex.positionOffset,
Vertex.size());
gl4.glVertexArrayAttribFormat(0, 0, 3, GL4.GL_FLOAT, false, Vertex.size());
// Set up attribute 1 for the color (4 unsigned bytes)
gl4.glVertexArrayVertexBuffer(0, 1, vertexBuffer[0], Vertex.colorOffset,
Vertex.size());
gl4.glVertexArrayAttribFormat(0, 1, 4, GL4.GL_UNSIGNED_BYTE, true, Vertex.size());
And then I finish the render:
// Reset state
gl4.glDisableVertexArrayAttrib(0, 0);
gl4.glDisableVertexArrayAttrib(0, 1);
I admit I never used dsa before, I always used GL3 with the normal vbo, vao and ibo, binding and unbinding..
Culling is off.
What's wrong then?
Solved, the problem was I didnt implement properly dsa
glEnableVertexAttribArray(vao, 0);
glEnableVertexAttribArray(vao, 1);
// Setup the formats
glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribFormat(vao, 1, 2, GL_FLOAT, GL_FALSE, 0);
// Setup the buffer sources
glVertexArrayVertexBuffer(vao, 0, buffers[0], 0, 0); // Note the 2nd argument here is a 'binding index', not the attribute index
glVertexArrayVertexBuffer(vao, 1, buffers[1], 0, 0);
// Link them up
glVertexArrayAttribBinding(vao, 0, 0); // Associate attrib 0 (first 0) with binding 0 (second 0).
glVertexArrayAttribBinding(vao, 1, 1);
plus glVertexArrayElementBuffer if you have indexed rendering

Should vertex data be laid out on per-pertex or per-attribute basis?

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.