0
\$\begingroup\$

I am currently using standard modern OpenGL way to render a mesh via VBO and attributes

    glEnableVertexAttribArray(aVertexPosition);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glVertexAttribPointer(aVertexPosition, 3, GL_FLOAT, GL_FALSE, 0,0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

and in the GLSL code also the standard way to received into as in vec3 aVertexPosition.

However, I wonder if there is anyway to make this for a dynamic amount of VBOs. Let's say my software creates a number of VBOs that depend on the inputs, and I successfully create and allocate memory for all of them, how do I pass all of them to the shader? Does the number need to be constant? If so, what is the best way to do it?

\$\endgroup\$
2
\$\begingroup\$

In DirectX this is called the input signature. In older version of DX (DX9) you could skip to plug a stream-source, and then all unplugged things in the shader would default to zero value. (zero value filled from void by the pipeline).
I would suppose OpenGL also does this kind of things.

Note the newer versions of the graphics libraries (DX10+) do not accept unbound data to be passed to a vertex shader. I don't know the details on OpenGL core 3.3+ on this subject, but if it followed DX10 philosophy then there is no way to do this flexibly.

You need to create all the combinations of the shaders that will accept the streams as input, and your engine (on the CPU side) needs to plug the good shader according to the attributes combination that you have got.
You can generate the combinations using #defines and turning them ON/OFF using binary counting at compile time, in a loop, and store the whole thing using an integer ID as a key, that you can create as a binary flag combination of the presence of your attributes. This is a compact hash so you can use an array to store the result, but careful, 5 attributes = 32 combinations.
Then in the shader, you can also use the defines to do something with the source when it is present.

\$\endgroup\$
1
\$\begingroup\$

I agree with what v.oddou said. An extra point, changing the number of inputs of the shader can be thought of as changing an interface of a function, they are not strictly the same but the concept applies. So expect by default a recompile for your shaders to add more input streams, you also need to modify your code to pass those streams. You can use #define to support multiple inputs.

\$\endgroup\$
  • \$\begingroup\$ Understood. I never thought I would have to change to shader code and recompile to make inputs dynamic! Good idea though :) \$\endgroup\$ – Dan Oct 9 '14 at 18:23
0
\$\begingroup\$

I'm not quite sure whether I understand you correctly, but you can assign different buffer objects to different attributes. The buffer object currently bound while calling glVertexAttribPointer will be used as the data source:

If a non-zero named buffer object is bound to the GL_ARRAY_BUFFER target (see glBindBuffer) while a generic vertex attribute array is specified, pointer is treated as a byte offset into the buffer object's data store.

Also, the buffer object binding (GL_ARRAY_BUFFER_BINDING) is saved as generic vertex attribute array client-side state (GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) for index index.

\$\endgroup\$
  • \$\begingroup\$ I know you can assign different buffer objects to different attributes, the problem is when you don't know the amount of VBOs at compilation time, you don't know how many vertex attributes you need to define. \$\endgroup\$ – Dan Oct 9 '14 at 18:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.