Подпрограмма GLSL не изменена

Я начал изучать GLSL и OpenGL. Прямо сейчас я пытаюсь увидеть, как работают подпрограммы GLSL, поэтому у меня есть фрагментный шейдер:

#version 330 core

out vec4 color;

subroutine vec4 ColorFunc();

subroutine (ColorFunc) vec4 colorBlue() {
    return vec4(0.0, 0.0, 1.0, 1.0);
}

subroutine (ColorFunc) vec4 colorGreen() {
    return vec4(0.0, 1.0, 0.0, 1.0);
}

subroutine uniform ColorFunc ColorSelector;

void main() {
    color = ColorSelector();
}

В исходнике приложения загружаю, компилирую ссылку на шейдер и запускаю программу сначала. Создается треугольник, и вершинный шейдер не делает ничего особенного. Функция display (отправленная glutDisplayFunc) выглядит следующим образом:

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);

    glBindVertexArray(TriangleVAO);
    glDrawArrays(GL_TRIANGLES, 0, NumVertices);

    GLint ColorSelectorLoc;
    GLuint colorBlueIndex;
    GLuint colorGreenIndex;

    ColorSelectorLoc = glGetSubroutineUniformLocation(program, GL_FRAGMENT_SHADER, "ColorSelector");
    if (ColorSelectorLoc < 0)
    {
        fprintf(stderr, "Error: ColorSelector is not an active subroutine uniform in the shader\n");
        exit(EXIT_FAILURE);
    }

    colorBlueIndex = glGetSubroutineIndex(program, GL_FRAGMENT_SHADER, "colorBlue");
    colorGreenIndex = glGetSubroutineIndex(program, GL_FRAGMENT_SHADER, "colorGreen");

    GLsizei n;
    glGetProgramStageiv(program, GL_FRAGMENT_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &n);
    GLuint *indices = new GLuint[n];
    cout << "colorGreen: " << colorBlueIndex;
    indices[ColorSelectorLoc] = colorGreenIndex;
    glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, n, indices);
    delete [] indices;

    glFlush();
}

Я ожидаю, что треугольники будут зелеными, но они всегда синие, независимо от значения ColorSelector, которое получено правильно (его значение равно 0). colorBlueIndex равно 0, а colorGreenIndex равно 1. Я не знаю, что мне не хватает.


person ali    schedule 30.04.2014    source источник
comment
заменить GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS на GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS​   -  person ratchet freak    schedule 30.04.2014
comment
Я сделал, но ничего. С GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS n равно 4096, но с GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS​ это какое-то странное число (31498976), которое выглядит как указатель на что-то.   -  person ali    schedule 30.04.2014


Ответы (2)


вызов glUniformSubroutinesuiv ожидает, что n будет равно количеству активных местоположений подпрограммы

вы можете получить это с помощью:

glGetProgramStage(program, GL_FRAGMENT_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &n);

см. вики

person ratchet freak    schedule 30.04.2014
comment
glGetProgramStage возвращает 1 активную подпрограмму (правильно ли это?). Треугольник по-прежнему синий. Индекс не меняется - person ali; 30.04.2014
comment
вы, кажется, никогда не устанавливали color2Index - person ratchet freak; 30.04.2014
comment
Сой, была опечатка. Это ColorGreenIndex. Я не понимаю, почему вызывается первая подпрограмма. Если в шейдере я передвину colorGreen() перед colorBlue(), то он станет зеленым. Таким образом, он всегда вызывает первую подпрограмму. - person ali; 30.04.2014
comment
@ali какие-нибудь glErrors? при этом - person ratchet freak; 30.04.2014
comment
Я получаю ошибку OpenGL: 1280, но я получаю ее до выполнения подпрограммы. - person ali; 30.04.2014
comment
это ошибка 0x500: недопустимое перечисление (см. здесь), посмотрите, где оно активируется в первую очередь (следуйте каждому звонок с таким чеком) - person ratchet freak; 30.04.2014
comment
Это странно. Это происходит после этого кода: if (glewInit()) { cerr << "Unable to initialize GLEW ... exiting" << endl; exit(EXIT_FAILURE); }. GLEW не выдает никаких ошибок - person ali; 30.04.2014
comment
GLEW инициализируется правильно, но после этого я получаю ошибку GL_INVALID_ENUM. Тем не менее, треугольник нарисован - person ali; 30.04.2014
comment
ХОРОШО. Исправлена ​​ошибка glew (stackoverflow.com/questions/19453439/), но мне все еще не удается вызвать правильную подпрограмму - person ali; 30.04.2014

Я нашел проблему. Код подпрограммы должен стоять перед glDrawArrays:

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);

    GLint ColorSelectorLoc;
    GLuint colorBlueIndex;
    GLuint colorGreenIndex;

    ColorSelectorLoc = glGetSubroutineUniformLocation(program, GL_FRAGMENT_SHADER, "ColorSelector");
    if (ColorSelectorLoc < 0)
    {
        fprintf(stderr, "Error: ColorSelector is not an active subroutine uniform in the shader\n");
        exit(EXIT_FAILURE);
    }

    colorBlueIndex = glGetSubroutineIndex(program, GL_FRAGMENT_SHADER, "colorBlue");
    colorGreenIndex = glGetSubroutineIndex(program, GL_FRAGMENT_SHADER, "colorGreen");

    GLsizei n;
    glGetProgramStageiv(program, GL_FRAGMENT_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &n);
    GLuint *indices = new GLuint[n];
    cout << "colorGreen: " << colorBlueIndex;
    indices[ColorSelectorLoc] = colorGreenIndex;
    glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, n, indices);
    delete [] indices;

    glBindVertexArray(TriangleVAO);
    glDrawArrays(GL_TRIANGLES, 0, NumVertices);

    glFlush();
}
person ali    schedule 30.04.2014