Advertisement

Problem Arising from Using One Shader for Multiple VAOs

Started by September 12, 2019 05:07 PM
2 comments, last by Green_Baron 5 years, 3 months ago

This question is based on a completely hypothetical situation which has occurred to me. It is not a problem I am actually having, just one that I think could potentially occur in the future.

Suppose that we have two vertex array objects - Squares_VAO and Trapezium_VAO:


std::array<float, 18> square_vertices
{
	   -0.75F, 1.0F , 1.0F , // Position (Attribute 0)
		0.5F , 0.0F , 0.0F , // Colour (Attribute 1)
	   -1.0F , 1.0F , 1.0F , 
		0.5F , 0.0F , 0.0F , 
	   -1.0F , 1.0F , 0.75F, 
		0.5F , 0.0F , 0.0F ,
	   -0.75F, 1.0F , 0.75F, 
		0.5F , 0.0F , 0.0F   
};

Squares_VBO(squares_vertices); // sets up squares vbo...
Squares_VAO; // sets up squares vao...

std::array<float, 18> trapezium_vertices
{
	   -0.75F, 1.01F, 1.0F , // Colour (Attribute 0)
		0.5F , 0.0F , 0.0F , // Position (Attribute 1)
	   -1.0F , 1.0F , 1.0F ,
		0.5F , 0.0F , 0.0F , 
	   -1.0F , 1.0F , 0.75F, 
		0.5F , 0.0F , 0.0F ,  
	   -0.75F, 1.0F , 0.75F,
		0.5F , 0.0F , 0.0F 
};

Trapezium_VBO(trapezium_vertices); // sets up trapezium vbo...
Trapezium_VAO; // sets up trapezium vao...

The only difference between square_vertices and trapezium_vertices is that the position and colour attributes have swapped positions; in square_vertices, position and colour are attributes 0 and 1 respectively, and then vice versa for trapezium_vertices. 

Suppose that the shader looks something like this:


#vertex shader
#version 330 core

layout(location = 0) in vec4 position;
layout(location = 1) in vec4 colours;

//...

There would obviously be an issue here where for the Trapezium_VAO, the attributes are going to be fetched the wrong way round (i.e. position will be attribute 0 and colour will be attribute 1). Obviously you could just correct this in trapezium_vertices (by swapping the location of the attributes), but suppose that for whatever reason this isn't possible - what would one do to solve this?

There could be other scenarios similar to this, for example the attribute at a given location being a vec3 in one VAO and a vec4 in another VAO:


std::array<float, 8> square_vertices
{
  -0.75F, 1.0F, 1.0F, 0.5F  // Position (Attribute 0) ...
   0.5F , 0.0F, 0.0F, 0.0F 
};

std::array<float, 6> triangle_vertices
{
  -0.75F, 1.0F, 1.0F,  // Position (Attribute 0) ...
   0.5F , 0.0F, 0.0F 
};

...
  
#vertex shader
#version 330 core

layout(location = 0) in vec4 position; 
// will only work for square_vertices, since has 4 components per vertex..
// whereas triangle_vertices has 3 components per vertex...

How could one get around this?

 

The sequence in the buffer plays no role, just assign the attributes to their correct shader attribute locations via glVertexAttribPointer or the more modern variants glVertexArrayAttribFormat / glVertexAttribFormat.

And if this still is not possible then you'll have to use OpenGLs separable shader feature to switch only the vertex stage, but that's probably much more hassle than just switching the shader locations .... or use two pipelines.

But it IS possible. Build the buffers as you see fit, with interleaved attributes or consecutive, sequence whatever, and use the attribute descriptions to tell the shader interface who's who.

Advertisement

Buuut .... looking ahead, one day there may be a lot of shaders and a lot vertex- and index buffers. It is surely a good idea to find a standardisation or guideline for one's engine or framework, so that the shader interfaces (vertex stage input as well as between stages) have some sort of comprehensible naming with pre- or suffixes, often used shader uniform locations are comparable or even fixed (like camera position is always x, view matrix always y, etc. pp. the list can get long) and array locations have an order as well (positions always 0, normals always 1, etc.).

Whatever makes the living easier ...

This topic is closed to new replies.

Advertisement