OpenGL 4.2 glBindAttribLocation недопустимое значение?

Я использую OpenGL 4.2 и не могу понять, почему я получаю ошибку GL_INVALID_VALUE в этой программе. Я получаю сообщение об ошибке при вызове glBindAttribLocation. Согласно справочной странице OpenGL 4, есть только две причины почему GL_INVALID_VALUE следует генерировать из glBindAttribLocation.

void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name);

  1. INVALID_VALUE генерируется, если индекс равен или больше MAX_VERTEX_ATTRIBS.
  2. INVALID_VALUE генерируется, если программа не является значением, сгенерированным OpenGL.

Как видно из приведенной ниже программы, условие 1 не задано, поскольку index равно 20, а GL_MAX_VERTEX_ATTRIBS равно 34921. Условие 2 не выполняется, поскольку program генерируется OpenGL с использованием glCreateProgram(). Так как же я мог получить ошибку GL_INVALID_VALUE?

// test.cpp
#include <GL/glew.h>
#include <GL/glut.h>
#include <iostream>

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutCreateWindow("Test");
    glewInit();

    std::cout << "Max Vertex Attributes : " << GL_MAX_VERTEX_ATTRIBS << std::endl;
    // create program
    GLuint program = glCreateProgram();
    if ( program == 0 )
        std::cout << "Program error" << std::endl;

    // clear existing errors        
    if ( glGetError() != GL_NO_ERROR )
        std::cout << "Pre-existing error" << std::endl;

    // bind attribute location to index 20
    glBindAttribLocation(program, 20U, "DoesNotExist");

    // why is this generating an INVALID_VALUE error?
    if ( glGetError() == GL_INVALID_VALUE )
        std::cout << "Invalid value error" << std::endl;

    glDeleteProgram(program);
    return 0;
}

Терминальный выход

$ g++ test.cpp -lGLEW -lglut
$ ./a.out 
Max Vertex Attributes : 34921
Invalid value error

Также для проверки OpenGL 4.2

$ glxinfo | grep OpenGL
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce GT 540M/PCIe/SSE2
OpenGL version string: 4.2.0 NVIDIA 304.64
OpenGL shading language version string: 4.20 NVIDIA via Cg compiler
OpenGL extensions:

Примечание. Согласно справочной странице. «glBindAttribLocation можно вызывать до того, как какие-либо объекты вершинного шейдера будут привязаны к указанному программному объекту. Также допустимо привязывать общий индекс атрибута к имени переменной атрибута, которое никогда не используется в вершинном шейдере». Так что проблема не в том, что шейдеры не загружены и DoesNotExist не существует.


person jodag    schedule 29.09.2013    source источник
comment
может быть ошибка драйвера, но почему вы это делаете? Я не вижу никакого смысла ... также с 4.2 у вас есть явное местоположение атрибута.   -  person yngccc    schedule 29.09.2013
comment
Это просто фиктивная программа для воспроизведения ошибки в гораздо большей программе. Я знаю, что в версии 4.2 я могу определять расположение своих атрибутов в своем шейдере, но я структурировал свою программу таким образом, чтобы привязка местоположений была оптимальной. Также это повторяется на другой моей машине с OpenGL 4.2 с Nvidia 560 GTX. попробую обновить драйвера   -  person jodag    schedule 29.09.2013


Ответы (1)


Я уже второй раз за пару месяцев припоминаю, что мне задают этот вопрос. Последний раз, когда это задавали, хотя сразу не видно, что это тот же вопрос, был здесь.

Это сводится к следующему: GL_MAX_VERTEX_ATTRIBS как видит компилятор, это токен препроцессора, который определяет идентификатор, который вы можете использовать, чтобы запросить у драйвера OpenGL его ограничение, определенное реализацией, во время выполнения. Когда вы пытаетесь напечатать это значение напрямую, единственное, что вы делаете, это печатаете универсальный идентификатор, который все реализации OpenGL используют для запроса этого конкретного ограничения.

Чтобы получить фактическое ограничение, зависящее от реализации, вам нужно сделать это во время выполнения:

int max_attribs;
glGetIntegerv (GL_MAX_VERTEX_ATTRIBS, &max_attribs);

Между прочим, от реализации OpenGL требуется не менее 16 атрибутов для каждой вершины; большинство дает вам только минимум, что объясняет, почему 20 за пределами допустимого.

person Andon M. Coleman    schedule 29.09.2013
comment
Замечательный! Я проверил, и вы правы, GL_MAX_VERTEX_ATTRIBS на самом деле 16. - person jodag; 29.09.2013
comment
Теперь самое сложное: вы действительно используете 20 атрибутов для каждой вершины? :) Если это так, вам нужно найти способы значительно упростить структуру данных вершин. Обратите внимание, что такие вещи, как mat4, занимают 4 слота атрибутов вершин. - person Andon M. Coleman; 29.09.2013
comment
Ха-ха, мне не нужно 20 атрибутов для каждой вершины, отчасти причина в том, что я использую один VBO с несколькими программами с разными вершинными шейдерами. Ни один вершинный шейдер не имеет более 4 атрибутов вершин. - person jodag; 29.09.2013
comment
Ой, я имел в виду сингл VAO, а не VBO - person jodag; 29.09.2013
comment
Приведенный выше фрагмент кода возвращает мне очень большое число (вероятно, это происходит для атрибута, который не всегда установлен). Я предполагаю, что GL_MAX_VERTEX_ATTRIBS не всегда устанавливается на всех платформах. - person ; 16.08.2016
comment
Я предполагаю, что у вас нет активного контекста рендеринга, когда вы делаете этот вызов, и он не имеет никакого эффекта, оставляя запрошенное вами значение неинициализированным. Контексты рендеринга используют локальное хранилище потока, поэтому вам нужно не только активное хранилище, но и в вызывающем потоке. - person Andon M. Coleman; 16.08.2016