Search code examples
openglglsl

Using vertex attribute variable as an index of UBO's array


I try to use attribute variable as an index to array in uniform buffer object. While linking the program I get linking error, but unfortunately there is no additional error descriptions. If I change a_Index to constant in vertex shader, everything works fine. Help me please)) What is wrong here?

This is my vertex shader:

#version 430

layout(location = 0) in vec2 a_Position;
layout(location = 1) in int a_Index;

struct Node {
    mat4 model;   // 0  (column 0)
                  // 16 (column 1)
                  // 32 (column 2)
                  // 48 (column 3)
    vec4  color;  // 64 
    float depth;  // 68
    float type;   // 72
};

layout(std140, row_major) uniform LinesBuffer {
    Node nodes[];
};

out vec4 v_vertex_Color;
out float v_vertex_Depth;

uniform mat4 u_Projection;
uniform mat4 u_View;
uniform mat4 u_Model;

void main()
{
    Node node = nodes[a_Index];

    if (node.type == 0.0) 
    {
        return;
    }

    v_vertex_Color = node.color;
    v_vertex_Depth = node.depth;

    gl_Position =  u_Projection * u_View * u_Model * node.model * vec4(a_Position, 0.0, 1.0);
}

Fragment shader:

#version 430

in vec4 v_vertex_Color;
in float v_vertex_Depth;
layout(location = 0) out vec4 color;

void main()
{
    gl_FragDepth = v_vertex_Depth;
    color = v_vertex_Color;
}

The code that is used to fetch error message (logLen equals to zero):

    int logLen;
    glGetProgramiv(this->glId, GL_INFO_LOG_LENGTH, &logLen);

    if (logLen > 0)
    {
        char* log = new char[logLen];

        int written;
        glGetProgramInfoLog(this->glId, logLen, &written, log);

        fprintf(stderr, "Program log: \n%s", log);

        delete[] log;
    }

Solution

  • See OpenGL Shading Language 4.60 Specification (HTML) - 4.1.9. Arrays

    [...] Except for the last declared member of a shader storage block [...], the size of an array must be declared (explicitly sized) before it is indexed with anything other than a constant integral expression. [...]

    Note, "with anything other than a constant integral expression." is exactly what you do (nodes[a_Index] instead of nodes[0]).

    So you have 2 options:

    1. declare the size of the array.

    2. use a Shader Storage Block instead of a Uniform Block. e.g.:

      layout(std140, row_major) buffer LinesBuffer {
          Node nodes[];
      };