Sign in to follow this  

Vertex Attributes, VAOs and Shaders

This topic is 2008 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to come up with a clever abstraction for shaders for my project and I'm stumbling on this issue concerning VAOs. So, when you've got a shader bound and you want to bind a VBO for rendering you ask the shader for the location of each attribute your VBO contains data for. This way it's just a step when you're binding a VBO / Shader, correct? If I've got this part right, then where do VAOs fit in with their ability to essentially cache the operations necessary to bind a VBO? To clarify, say I've got ShaderA bound, and I set up a VAO that records what is necessary to bind a VBO. I find out from the shader that "position" is at location 1, "color" is at location 2 and "normal" is at location 3. When I call glEnableVertexAttribute and similar operations, the VAO is recording simply the integer value going into these functions (1, 2, or 3 in this example) not the fact that I've queried the current shader to find out where they actually are. So now if I swap ShaderA for ShaderB and bind that same VAO for drawing, but ShaderB happens to have "position", "color" and "normal" at 2, 3, and 1 respectively, the VAO is going to bind the data in the wrong order and mess everything up.

All I can think of is to statically enforce the location of vertex attributes in the shader code, but this seems like the wrong thing to do. Is this my only option?

Share this post


Link to post
Share on other sites
You are correct. If you have two different shaders with differently bound input attribute positions, you can't use the same VAO to render with both shaders.

What I do is I make all my shader programs to use a compatible layout that are intended to be used with the same VAO. A compatible layout can have extra stuff, i.e program with { index0: pos, index1: normal, index2: uv} and a program with { index0: pos, index1: normal} are compatible, since the common portion of them is identical. I have a function AreCompatible(ShaderProgram, VAO) that checks the objects that the VAO and shader program agree with the stored state. This check is enabled at debug time and it yells red text in the console if not. That way I can manually author my shader programs and VAOs to use a common structure wherever necessary, and in release mode, the checks don't exist and there is no overhead.

So, essentially, in my case, I am able to get around the potential problems by rules of convention.

Share this post


Link to post
Share on other sites
[quote name='clb' timestamp='1339739842' post='4949446']
So, essentially, in my case, I am able to get around the potential problems by rules of convention.
[/quote]

Heh, I was just coming back here to update and say that I spent the last hour or so implementing a static system just to see how it worked out, and I think I like it.

Like I said before, it was clever to be able to do it dynamically with hash maps of attribute names and locations but not being able to use VAOs was a huge strike against it. The new code is also simpler. I'm glad to see someone else taking this approach as well as it gives me confidence that this is viable (not that I saw many other options like I said).

I'm still interested in any other opinions / techniques people have got though!

Share this post


Link to post
Share on other sites
There are a couple of ways to achieve this.

One way is to use the "layout" specifier, and use a convention to make sure it is always the same. Another way is to have the layout declaration in a common string, that is included into the shaders before they are compiled. That way, you only have one common source.

Another way, which is compatible with OpenGL 3.0, is to tell OpenGL the locations in the compilation process of the shader (glBindAttribLocation I think it was). You have to do this before the linkage phase. I use this method, using a common base class with a callback function.

Share this post


Link to post
Share on other sites

This topic is 2008 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this