Search code examples
c++openglglslglad

How to read the VAO from the GLSL shader, or pass an Array of indefinite size to the shader?


I partially managed to implement rendering by individual indexes - by loading the indexes into VAO, setting their layout, and passing them using glDrawArrays

but now another problem - for test i created arrays in shader itself -

`

#version 330 core

// Positions/Coordinates
layout (location = 0) in int V_Indices;
// Colors
layout (location = 1) in int T_Indices;
// Texture Coordinates
layout (location = 2) in int N_Indices;

 
 


vec3 Vertices[8] = vec3[8]( 
vec3(- 1.000000, -1.000000, 1.000000),
vec3(-1.000000,  1.000000, 1.000000 ),
vec3(-1.000000, -1.000000, -1.000000),
vec3(-1.000000,  1.000000, -1.000000),
vec3( 1.000000, -1.000000, 1.000000),
vec3( 1.000000,  1.000000, 1.000000),
vec3( 1.000000, -1.000000, -1.000000),
vec3( 1.000000,  1.000000, -1.000000));
//
vec2 Texcoords[] = vec2[22](

    vec2( 0.333333, 0.333333),
    vec2( 0.666667, 0.000000),
    vec2( 0.666667, 0.333333),
    vec2( 0.000000, 0.666667),
    vec2( 0.333333, 0.333333),
    vec2( 0.333333, 0.666667),
    vec2( 0.000000, 0.333333),
    vec2( 0.333333, 0.000000),
    vec2( 0.333333, 0.333333),
    vec2( 0.666667, 0.666667),
    vec2( 0.333333, 0.666667),
    vec2( 0.666667, 0.333333),
    vec2( 1.000000, 0.000000),
    vec2( 1.000000, 0.333333),
    vec2( 0.333333, 1.000000),
    vec2( 0.000000, 0.666667),
    vec2( 0.333333, 0.666667),
    vec2( 0.333333, 0.000000),
    vec2( 0.000000, 0.000000),
    vec2( 0.666667, 0.333333),
    vec2( 0.666667, 0.000000),
    vec2( 0.000000, 1.000000)
);

vec3 Normals[] = vec3[6](
     vec3(-1.0000,  0.0000, 0.0000),
     vec3( 0.0000,  0.0000, -1.0000),
     vec3( 1.0000,  0.0000, 0.00000),
     vec3( 0.0000,  0.0000, 1.00000),
     vec3( 0.0000, -1.0000, 0.0000),
     vec3( 0.0000,  1.0000, 0.0000)
);

out vec2 texCoord;

uniform mat4 camMatrix;


void main()
{
    // Outputs the positions/coordinates of all vertices
    gl_Position = camMatrix * vec4(Vertices[V_Indices], 1.0);
    // Assigns the colors from the Vertex Data to "color"

    // Assigns the texture coordinates from the Vertex Data to "texCoord"
    texCoord = Texcoords[T_Indices];
}

`

But in real conditions, it will not work to make arrays in the shader, moreover, the arrays will be of different lengths The question is - is it possible to load an array of vertices into a VBO and then either get a VBO from a shader - as an array, or somehow read its elements by index If not, then the question is - is it possible to make a dynamic array in the shader, and then pass vertexes to it? - "uniform int ArrSize" "uniform vec3 *arr = new vec3 [ArrSize]; enter image description here

enter image description here


Solution

  • The best fit for this task would be a Shader Storage Buffer Object:

    layout(std430, binding=0) buffer VertexBuffer { vec3 Vertices[]; };
    layout(std430, binding=1) buffer TexcoordBuffer { vec2 Texcoords[]; };
    layout(std430, binding=2) buffer NormalBuffer { vec3 Normals[]; };
    ...
    void main() {
        gl_Position = camMatrix * vec4(Vertices[V_Indices], 1.0);
        texCoord = Texcoords[T_Indices];
    }
    

    You'd bind the buffers with:

    GLuint buffers[] = { vertexBuffer, texcoordBuffer, normalBuffer };
    GLintptr offsets[] = { ... };
    GLsizeiptr sizes[] = { ... };
    glBindBuffersRange(GL_SHADER_STORAGE_BUFFER, 0, 3, buffers, offsets, sizes);
    

    Although the layout of SSBOs is less flexible than VAOs, they do allow indexing very big buffers (usually as big as you can allocate).

    However, SSBOs were introduced in OpenGL 4.3, and may only be available on earlier versions through an extension.

    If you'd like it to work with earlier OpenGL versions, you may look at Uniform Buffer Objects or Buffer Textures.