PDA

View Full Version : Unable two render two separate objects with two VAOs



Aska49
09-04-2016, 03:48 PM
Hello.

I'm pretty new to the modern GL pipeline even though I feel like I understand it pretty well. I'm setting up a simple test to render two textured triangles next to eachother.

I have one shader and one texture. I create two VAOs, two VBOs, fill those VBOs with float data, and proceed in this order:


Bind VAO1
Bind VBO1
Set and enable VertexAttribPointers
Bind VAO2
Bind VBO2
Set and enable VertexAttribPointers

Drawing looks like this:


Enable shader
Bind VAO1
glDrawArrays
Bind VAO2
glDrawArrays

This is my output:
2290

As you can see it's only drawing one of my objects. If I remove the Bind VBO2 call referenced in the first note above, the object on the left then draws but obviously the second one no longer does. Am I misunderstanding something about the way you're supposed to use these objects?

This is the relevant code, all there is besides this is using SDL to get a window to draw to and receive input.

Init code, ran once:

//openGL state setup
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

mat4x4 ViewMatrix;
mat4x4 ProjMatrix;
v3 Cam = V3(0.0f, 0.0f, 2.0f);

// shader
gl_shader_program WorldShader;
GLLoadShaderProgram(&WorldShader, "shaders/default.vert", "shaders/default.frag");
GLUseShader(&WorldShader);

glUniform1i(glGetUniformLocation(WorldShader.Progr am, "diffuse"), 0);

// texture
gl_texture Texture;
GLLoadTexture(&Texture, "textures/shooter.png");

// vao
GLuint VAO;
glGenBuffers(1, &VAO);
GLuint VAO2;
glGenBuffers(1, &VAO2);

// vbo
r32 Verts[] = {
-1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-1.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
};
r32 Verts2[] = {
1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.5f, 0.0f,
1.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
};

GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Verts), Verts, GL_STATIC_DRAW);
GLuint VBO2;
glGenBuffers(1, &VBO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(Verts2), Verts2, GL_STATIC_DRAW);

glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(0));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(3*sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(7*sizeof(float)));
glEnableVertexAttribArray(2);

glBindVertexArray(VAO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(0));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(3*sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(7*sizeof(float)));
glEnableVertexAttribArray(2);


Running loop:


r32 AspectRatio = (Window.Resolution.w / Window.Resolution.h);

ViewMatrix = LookAt(Cam, V3(), V3(0.0f, 1.0f, 0.0f));
ProjMatrix = Perspective(AspectRatio, 0.1f, 1000.0f, 60.0f);

glUniformMatrix4fv(glGetUniformLocation(WorldShade r.Program, "View"),
1, GL_TRUE, &ViewMatrix.A[0]);
glUniformMatrix4fv(glGetUniformLocation(WorldShade r.Program, "Proj"),
1, GL_TRUE, &ProjMatrix.A[0]);

// do render

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

GLUseShader(&WorldShader);

glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);

glBindVertexArray(VAO2);
glDrawArrays(GL_TRIANGLES, 0, 3);

SDL_GL_SwapWindow(Window.WindowHandle);

Shaders:

// vert
#version 330

layout(location = 0) in vec3 position;
layout(location = 1) in vec4 color;
layout(location = 2) in vec2 uv;

out vec4 Color;
out vec2 UV;

uniform mat4 View;
uniform mat4 Proj;

void main()
{
vec4 InputPos = vec4(position, 1.0f);
InputPos.y *= -1.0f;

Color = color;
UV = uv;

gl_Position = Proj * View * InputPos;
}


// frag
#version 330

in vec4 Color;
in vec2 UV;

out vec4 outColor;

uniform sampler2D diffuse;

void main()
{
vec4 inColor = texture(diffuse, UV)*Color;
outColor = inColor;
}

Thanks.

Cornix
09-04-2016, 03:59 PM
I think you would have to show us some of your actual code. Try to narrow your code down to the smallest program that reproduces your problem. There are plenty of possible reasons for your problem, without more details its hard to pinpoint.

Aska49
09-04-2016, 04:27 PM
Sorry about that, you're right. I don't know why I didn't include any of the actual code. I'll put it here and edit the post. Thanks for the speedy reply.

This is the relevant code, all there is besides this is using SDL to get a window to draw to and receive input.

Init code, ran once:

//openGL state setup
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

mat4x4 ViewMatrix;
mat4x4 ProjMatrix;
v3 Cam = V3(0.0f, 0.0f, 2.0f);

// shader
gl_shader_program WorldShader;
GLLoadShaderProgram(&WorldShader, "shaders/default.vert", "shaders/default.frag");
GLUseShader(&WorldShader);

glUniform1i(glGetUniformLocation(WorldShader.Progr am, "diffuse"), 0);

// texture
gl_texture Texture;
GLLoadTexture(&Texture, "textures/shooter.png");

// vao
GLuint VAO;
glGenBuffers(1, &VAO);
GLuint VAO2;
glGenBuffers(1, &VAO2);

// vbo
r32 Verts[] = {
-1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-1.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
};
r32 Verts2[] = {
1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.5f, 0.0f,
1.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
};

GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Verts), Verts, GL_STATIC_DRAW);
GLuint VBO2;
glGenBuffers(1, &VBO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(Verts2), Verts2, GL_STATIC_DRAW);

glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(0));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(3*sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(7*sizeof(float)));
glEnableVertexAttribArray(2);

glBindVertexArray(VAO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(0));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(3*sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(7*sizeof(float)));
glEnableVertexAttribArray(2);


Running loop:


r32 AspectRatio = (Window.Resolution.w / Window.Resolution.h);

ViewMatrix = LookAt(Cam, V3(), V3(0.0f, 1.0f, 0.0f));
ProjMatrix = Perspective(AspectRatio, 0.1f, 1000.0f, 60.0f);

glUniformMatrix4fv(glGetUniformLocation(WorldShade r.Program, "View"),
1, GL_TRUE, &ViewMatrix.A[0]);
glUniformMatrix4fv(glGetUniformLocation(WorldShade r.Program, "Proj"),
1, GL_TRUE, &ProjMatrix.A[0]);

// do render

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

GLUseShader(&WorldShader);

glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);

glBindVertexArray(VAO2);
glDrawArrays(GL_TRIANGLES, 0, 3);

SDL_GL_SwapWindow(Window.WindowHandle);

Shaders:

// vert
#version 330

layout(location = 0) in vec3 position;
layout(location = 1) in vec4 color;
layout(location = 2) in vec2 uv;

out vec4 Color;
out vec2 UV;

uniform mat4 View;
uniform mat4 Proj;

void main()
{
vec4 InputPos = vec4(position, 1.0f);
InputPos.y *= -1.0f;

Color = color;
UV = uv;

gl_Position = Proj * View * InputPos;
}


// frag
#version 330

in vec4 Color;
in vec2 UV;

out vec4 outColor;

uniform sampler2D diffuse;

void main()
{
vec4 inColor = texture(diffuse, UV)*Color;
outColor = inColor;
}

If there's any other info needed just let me know.

Silence
09-05-2016, 01:24 AM
Your uniforms seem to be sent to the same shader all the time:



ProjMatrix = Perspective(AspectRatio, 0.1f, 1000.0f, 60.0f);

glUniformMatrix4fv(glGetUniformLocation(WorldShade r.Program, "View"),
1, GL_TRUE, &ViewMatrix.A[0]);
glUniformMatrix4fv(glGetUniformLocation(WorldShade r.Program, "Proj"),
1, GL_TRUE, &ProjMatrix.A[0]);

// do render

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

GLUseShader(&WorldShader);


Send them to both shaders.

Aska49
09-05-2016, 09:06 AM
I'm only using one shader at the moment. Could you clarify?

I'm able to use one shader to render multiple different objects, right? I thought this was the case.

Aska49
09-05-2016, 03:50 PM
Not really sure where else to go with this. I've found that simply creating and binding a single VAO on startup, and setting VertexAttribPointers and drawing with VBOs directly before each draw call gives me the behavior I want:


// do render

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

GLUseShader(&WorldShader);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(0));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(3*sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(7*sizeof(float)));
glEnableVertexAttribArray(2);
glDrawArrays(GL_TRIANGLES, 0, 3);

glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(0));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(3*sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (void *)(7*sizeof(float)));
glEnableVertexAttribArray(2);
glDrawArrays(GL_TRIANGLES, 0, 3);

But isn't that the whole point of VAOs? To not have to run this many calls to glVertexAttribPointer and the like every time you want to draw new objects? Putting those same glBindBuffer and VertexAttrib calls between VAO binds on init (like in my previous post) and just binding VAOs for drawing instead leads to only my second object being drawn. Am I using them incorrectly? It seems really straightforward.

Silence
09-06-2016, 12:23 AM
True, you have a single shader. I got puzzled by your snaps... You should send uniforms to currently bound shaders so not before calling to glUseShader (there we can believe you are sending uniforms to a previously used one).

You are right, you should not reset the pointers once the VAO has been created.
I checked your code once again. It also seems that you don't bind your VAO before binding the VBO when setting the data. You should:



glGenBuffers(1, &VAO);
GLuint VAO2;
glGenBuffers(1, &VAO2);

// vbo
r32 Verts[] = {
-1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-1.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
};
r32 Verts2[] = {
1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.5f, 0.0f,
1.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
};

GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);


If this is not enough, you can try to check any OpenGL errors. You can also try to follow a tutorial. The first english one I just found is here (http://www.swiftless.com/tutorials/opengl4/4-opengl-4-vao.html).

Aska49
09-06-2016, 06:27 PM
Well don't I feel foolish...

Thank you for the replies. Make sure you're actually generating vertex array objects and not buffer objects when you want to work with VAOs!


glGenBuffers(1, &VAO);

should have been


glGenVertexArrays(1, &VAO);

I really don't know how I missed this after staring at this code for a couple of days now. Is there a way to mark this as solved?

Silence
09-07-2016, 02:42 AM
Make sure you're actually generating vertex array objects and not buffer objects when you want to work with VAOs!

Right. What is looking weird is that it worked with a single VAO... Which made me focus on this.


Is there a way to mark this as solved?

AFAIK, no.