GLSL передает дополнительные позиции источника света в виде юниформ-переменных в вершинный шейдер

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

Например, в моем вершинном шейдере у меня есть:

...
uniform vec3 light_pos;

...
varying vec3 frag_light_pos;

void main() {
    ...

    frag_light_pos = vec3(0.0f, 100.0f, 0.0f);
    //frag_light_pos = light_pos;

    ...
}

Где разница в моей сцене можно увидеть ниже.

Чтобы установить юниформ-переменную, я использую Qt QOpenGLShaderProgam::setUniformValue следующим образом.

QVector3D light_pos(0.0f, 100.0f, 0.0f);
m_ShaderProgram->setUniformValue("light_pos", light_pos);

Все мои другие униформы, mv, mvp и (trans(mv))^-1 работают, так что это не проблема с Qt. Где я ошибаюсь? Я ожидаю увидеть одно и то же изображение, используя любую версию.

Снимок экрана с использованием const vec3: const vec3

Снимок экрана с использованием универсального vec3: uniform vec3


Обновить

Я добавил glGetError после каждого вызова OpenGL в свой код, состоящий из одной функции. Я получаю сообщение об ошибке только тогда, когда я задаю униформу как с использованием API Qt, так и без него, как показано ниже:

/*
    QVector3D light_pos(0.0f, 100.0f, 0.0f);
    m_ShaderProgram->setUniformValue("frag_light_pos", light_pos); GL_CALL
/*/
    GLint light_id = glGetUniformLocation(m_ShaderProgram->programId(),
        "frag_light_pos"); GL_CALL
    glUniform3f(light_id, 10.0f, 10.0f, 10.0f); GL_CALL
//*/

Где GL_CALL определяется как:

#define GL_CALL GetGlErrors(__LINE__);

void GetGlErrors(int line)
{
    GLenum err_code;
    while ((err_code = glGetError()) != GL_NO_ERROR) {
#if __GL_WRAPPER_WINDOWS__
        char buffer[256];
        sprintf_s(buffer, "GL_ERROR is %d from %d\n", err_code, line);
        OutputDebugStringA(buffer);
#else
        printf("GL_ERROR is %d from %d\n", err_code, line);
#endif
    }
}

Вывод моей программы показывает мне строку с данной ошибкой:

GL_ERROR 1282 вместо 263


person Matthew Hoggan    schedule 27.03.2015    source источник


Ответы (1)


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

Полученный результат, вероятно, связан с интерполяцией различных переменных в растеризаторе, что означает, что frag_light_pos будет иметь разное значение для каждого пикселя (фрагмента). Можно было бы использовать переменную с квалификатором flat, чтобы «отключить» интерполяцию, но я не вижу причин, по которым вы могли бы это сделать.

person ebbs    schedule 27.03.2015
comment
Я переместил его во фрагментный шейдер с тем же результатом. Я сделал еще несколько копаний, пока строю свою структуру. Пожалуйста, смотрите обновление, чтобы опубликовать дополнительную информацию. - person Matthew Hoggan; 28.03.2015
comment
Убедитесь, что glGetUniformLocation не возвращает -1. - person ebbs; 28.03.2015
comment
В этом случае униформа будет vec3(0.0, 0.0, 0.0), что также может объяснить результат. - person ebbs; 28.03.2015
comment
Проблема заключалась в том, что шейдер не был привязан в момент установки униформы. Я сделал это слишком высоко. - person Matthew Hoggan; 28.03.2015