PDA

View Full Version : VAO, VBO acting strangely.



Meanz
12-24-2011, 09:17 AM
Just announcing theese functions

VBO

GLuint create() {
glGenBuffers(1, &vboId);
return vboId;
};




GLvoid bind(int __type__) {
glBindBuffer(__type__, vboId);
};


GLvoid unbind() {
glBindBuffer(0, 0);
}

VAO


GLuint create() { glGenVertexArrays(1, &vaoId);
return vaoId;
};


GLvoid bind() {
glBindVertexArray(vaoId);
};


GLvoid unbind() {
glBindVertexArray(0);
};

Here is my init code


float verts[4 * 3]; verts[0] = 0.0f; verts[1] = 5.0f; verts[2] = 0.0f;
verts[3] = 1.0f; verts[4] = 5.0f; verts[5] = 0.0f;
verts[6] = 1.0f; verts[7] = 5.0f; verts[8] = 1.0f;
verts[9] = 0.0f; verts[10] = 5.0f; verts[11] = 1.0f;


vao.create();
vao.bind();
{
vbo.create();
vbo.bind(GL_ARRAY_BUFFER);
{
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), &verts[0], GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
}
vbo.unbind();
}
vao.unbind();


And my draw code


vao.bind(); {
glDrawArrays(GL_QUADS, 0, 4);
}
vao.unbind();


For some reason my output is this

http://cboard.cprogramming.com/attachments/cplusplus-programming/11266d1324573425-gl-vbo-vao-weird.png

And the red circle indicates a point that is always on the center of the screen, even if I rotate the camera.

So, is there any obvious faults in my code?
I guess the code is sloppy, due to me beeing a java programmer.
C++ seems kinda odd

mobeen
12-24-2011, 10:11 AM
Hi,
Change this line

glVertexAttribPointer((GLuint)0, 4, GL_FLOAT, GL_FALSE, 0, 0);
to this

glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);


Reason: the second parameter of glVertexAttribPointer contains the number of components in one vertex which for your case is 3 not 4. See if this helps.

Meanz
12-24-2011, 04:05 PM
Damn, how did I miss that ;)
I honestly believed the parameter was for "how many vertices per unit" for instance for quads it would be 4 and for triangles it would be 3.

Thanks alot ;)

Meanz
12-24-2011, 06:57 PM
I would hate to create a new topic just for this, so I hope the community is observant and reads this post too.

I am trying to implement texture coordinates into my VAO / VBO solution.

Earlier I used glTexCoordPointer or something along thoose lines. But I am pretty sure I am not supposed to use that now.

Should I place the texture coordinates alongside the vertices?

texcoord, vertices, texcoord, vertice.
And how do I make sure OpenGL knows they are texture coordinates? I am having issues googling this. So any quick response, or response at all would be appreciated ;)

mhagain
12-24-2011, 10:25 PM
"glVertexAttribPointer (8, ..." is equivalent to glTexCoordPointer; you can find the rest of the mappings here: http://oss.sgi.com/projects/ogl-sample/registry/ARB/vertex_program.txt


Conventional Attribute Binding Generic Attribute Binding
------------------------------ -------------------------
vertex.position vertex.attrib[0]
vertex.weight vertex.attrib[1]
vertex.weight[0] vertex.attrib[1]
vertex.normal vertex.attrib[2]
vertex.color vertex.attrib[3]
vertex.color.primary vertex.attrib[3]
vertex.color.secondary vertex.attrib[4]
vertex.fogcoord vertex.attrib[5]
vertex.texcoord vertex.attrib[8]
vertex.texcoord[0] vertex.attrib[8]
vertex.texcoord[1] vertex.attrib[9]
vertex.texcoord[2] vertex.attrib[10]
vertex.texcoord[3] vertex.attrib[11]
vertex.texcoord[4] vertex.attrib[12]
vertex.texcoord[5] vertex.attrib[13]
vertex.texcoord[6] vertex.attrib[14]
vertex.texcoord[7] vertex.attrib[15]
vertex.texcoord[n] vertex.attrib[8+n]

Alfonse Reinheart
12-24-2011, 11:08 PM
"glVertexAttribPointer (8, ..." is equivalent to glTexCoordPointer

No, it most certainly is not.

The OpenGL specification is very clear on this: there is to be no aliasing (in GLSL) between generic attributes and fixed-function attributes. At all. Yes, NVIDIA drivers will still have aliasing, but this is incorrect behavior, and you should not rely upon it.

If you're still using fixed-function vertex processing, there's no point in you not using fixed-function vertex attribute passing (ie: glTexCoordPointer). If you're using shaders, then you should just use a user-defined attribute, and then you'll know whether it is a texture coordinate or something else.

Meanz
12-24-2011, 11:19 PM
So I assume you are saying that I should use a shader to define the behavior of my rendering?

mobeen
12-24-2011, 11:49 PM
Hi,
I would recommend using shaders and custom per-vertex attributes. Here is a tutorial which details how to do it.
http://spacesimulator.net/wiki/index.php?title=Tutorials:Texture_Mapping_(OpenGL3 .3)

Meanz
12-26-2011, 02:08 AM
Alright, I managed to make the shader draw textured geometry.
But now I want to add 2 samplers to the texture, so I can mix the images.

My init code


worldData.addTexCoord(0.0f, 1.0f); worldData.addVertex(x, y + slopeBL, z);
worldData.addTexCoord(1.0f, 1.0f); worldData.addVertex(x + 1.0f, y + slopeBR, z);
worldData.addTexCoord(1.0f, 0.0f); worldData.addVertex(x + 1.0f, y + slopeTR, z + 1.0f);
worldData.addTexCoord(0.0f, 0.0f); worldData.addVertex(x, y + slopeTL, z + 1.0f);

//VT
int stride = 5 * 4; //3 for position 2 for tex
vao.create();
vao.bind();
{
vbo.create();
vbo.bind(GL_ARRAY_BUFFER);
{
glBufferData(GL_ARRAY_BUFFER, worldData.getVertexByteSize(), &worldData.getVerticeData()[0], GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(0));
glVertexAttribPointer((GLuint)1, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(3*sizeof(float)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
}
vbo.unbind();
}
vao.unbind();


Draw Code:



GLint tex1 = worldShaderProgram.getUniformLocation("terrainTex");
worldShaderProgram.uniformi(tex1, 2);
GLint tex2 = worldShaderProgram.getUniformLocation("terrainTex2");
worldShaderProgram.uniformi(tex2, 3);

glClientActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texAtlas);
glClientActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, texAtlas2);

worldShaderProgram.use();
vao.bind();
{
glDrawArrays(GL_QUADS, 0, worldData.getNumVertices());
}
vao.unbind();
worldShaderProgram.useNone();


texAtlas and texAtlas2 are two different textures, it's tested and verified, even though no code assumes anything different.

My frag shader.



varying vec2 outTex;
uniform sampler2D terrainTex;
uniform sampler2D terrainTex2;

void main (void)
{
vec4 col = mix(texture2D(terrainTex, outTex), texture2D(terrainTex2, outTex), 0.5);
gl_FragColor = col;
}


I tried only using


gl_FragColor = texture2D(terrainTex, outTex);

and


gl_FragColor = texture2D(terrainTex2, outTex);


I get the same output.

Any obvious faults here?

mobeen
12-26-2011, 02:15 AM
Hi,
1) Replace glClientActiveTexture call with glActiveTexture like this,


glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texAtlas);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, texAtlas2);

2) You should query the uniform locations after you have use the shader program.
3) A performance note here. I would recommend setting the uniforms once when the texture is loaded rather than setting them each frame as you are doing it right now.

Meanz
12-26-2011, 02:24 AM
Thank you.

I corrected my code,

in the init after I compile and link my shaders.

I "use" my shader program and query the uniforms.
Then I "use none", and buffer my geometry.

This is my current draw code.



worldShaderProgram.use();
vao.bind();
{
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texAtlas);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, texAtlas2);
glDrawArrays(GL_QUADS, 0, worldData.getNumVertices());
}
vao.unbind();
worldShaderProgram.useNone();


Would this be a recommended drawing setup?

And also, in my init code. What happends if I use glActiveTexture after I bound my vao and vbo, will the next call to bind my vao do the glActiveTexture for me, or will I have to call glActiveTexture each time I bind my vao ?

mobeen
12-26-2011, 02:32 AM
VAO do not store active texture. Since opengl is a state machine once u set a state it remains in that state unless you change it. The reason I told u to do it at initialization was because you were not changing your textures therefore you should not rebind the same texture when it is already bound. What I recommend is something like this,
At initialization (after the progam is compiled and linked), you use the program, query the locations and set the textures like this


shader.use();
//set the uniforms
GLint tex1 = worldShaderProgram.getUniformLocation("terrainTex");
worldShaderProgram.uniformi(tex1, 2);
GLint tex2 = worldShaderProgram.getUniformLocation("terrainTex2");
worldShaderProgram.uniformi(tex2, 3);

//Load and bind the texture here
// assuming that you will call glBindTexture in LoadTexture
glActiveTexture(GL_TEXTURE2);
LoadTexture(...);

glActiveTexture(GL_TEXTURE3);
LoadTexture(...);

shader.useNone();

Now in display function you do it like this,


shaderuse();
vao.bind();
glDrawArrays(GL_QUADS, 0, worldData.getNumVertices());
vao.unbind();
shader.useNone();

see if this helps.