GLSL унифицированный ivec не устанавливается и имеет значение по умолчанию (неправильное), когда его просят - PullRequest
0 голосов
/ 03 сентября 2018

У меня есть сцена с несколькими программами GLSL (OpenGL 3.3). Эти программы используют разные шейдеры, которые похожи, но (будут) иметь некоторые различия. И у меня есть униформа ivec4 char1, названная одинаково для всех версий, которая имеет одинаковое значение и значение для всех программ. Эта униформа используется в функции dot1(...), которая используется в функции main() внутри шейдеров.

fragment3d.glsl:

#version 330 core

smooth in vec4 vertexPosition;
smooth in vec4 vertexColor;
smooth in vec4 vertexNormal;
out vec4 fragmentColor;

uniform ivec4 char1;
uniform float shineness;

float dot1(vec4 x, vec4 y)
{
    float result = 0.0;
    for (int i = 0; i < 4; i++)
    {
        result += char1[i] * x[i] * y[i];
    }
    return result;
}

void main()
{
    if (vertexNormal == vec4(0.0, 0.0, 0.0, 0.0))
    {
        fragmentColor = vertexColor;
    }
    else
    {
        vec4 lightDirection = vec4(1.0, 0.0, 0.0, 0.0) - vertexPosition;
        float lightNormInverse = inversesqrt(dot1(lightDirection, lightDirection));
        lightDirection *= lightNormInverse;
        float diffuseCoefficient = dot1(lightDirection, vertexNormal);
        vec4 reflectedDirection = 2 * diffuseCoefficient * vertexNormal - lightDirection;
        diffuseCoefficient = abs(diffuseCoefficient);
        float specularCoefficient = max(dot1(reflectedDirection, lightDirection), 0.0);
        if (specularCoefficient > 0.0 && shineness > 0.0)
        {
            specularCoefficient = pow(specularCoefficient, shineness);
        }
        vec3 diffuseColor = clamp(vertexColor.rgb * diffuseCoefficient, 0.0, 1.0);
        vec3 specularColor = clamp(vec3(0.5, 0.5, 0.5) * specularCoefficient, 0.0, 1.0);
        fragmentColor.rgb = diffuseColor + specularColor;
        fragmentColor.a = 1.0 - diffuseCoefficient * (1.0 - vertexColor.a);
    }
}

fragment3d-new.glsl

#version 330 core

smooth in vec4 geometryPosition;
smooth in vec4 geometryNormal;
smooth in vec4 geometryColor;
out vec4 fragmentColor;

uniform ivec4 char1;
uniform float shineness;

float dot1(vec4 x, vec4 y)
{
    float result = 0.0;
    for (int i = 0; i < 4; i++)
    {
        result += char1[i] * x[i] * y[i];
    }
    return result;
}

void main()
{
    if (geometryNormal == vec4(0.0, 0.0, 0.0, 0.0))
    {
        fragmentColor = geometryColor;
    }
    else
    {
        vec4 lightDirection = vec4(1.0, 0.0, 0.0, 0.0) - geometryPosition;
        float lightNormInverse = inversesqrt(dot1(lightDirection, lightDirection));
        lightDirection *= lightNormInverse;
        float diffuseCoefficient = dot1(lightDirection, geometryNormal);
        vec4 reflectedDirection = 2 * diffuseCoefficient * geometryNormal - lightDirection;
        diffuseCoefficient = abs(diffuseCoefficient);
        float specularCoefficient = max(dot1(reflectedDirection, lightDirection), 0.0);
        if (specularCoefficient > 0.0 && shineness > 0.0)
        {
            specularCoefficient = pow(specularCoefficient, shineness);
        }
        vec3 diffuseColor = clamp(geometryColor.rgb * diffuseCoefficient, 0.0, 1.0);
        vec3 specularColor = clamp(vec3(0.5, 0.5, 0.5) * specularCoefficient, 0.0, 1.0);
        fragmentColor.rgb = diffuseColor + specularColor;
        fragmentColor.a = 1.0 - diffuseCoefficient * (1.0 - geometryColor.a);
    }
}

Код инициализации C ++:

glUseProgram(0);
if (m_glProgram[GEOMETRY] != 0)
{
    glDeleteProgram(m_glProgram[GEOMETRY]);
}
if (m_glProgram[TRIANGLE] != 0)
{
    glDeleteProgram(m_glProgram[TRIANGLE]);
}
if (m_glProgram[TEXTURE] != 0)
{
    glDeleteProgram(m_glProgram[TEXTURE]);
}
GLuint vertexShaderGeometry = compileShader(GL_VERTEX_SHADER, vertex, ss);
GLuint fragmentShaderGeometry = compileShader(GL_FRAGMENT_SHADER, fragment, ss);
vector<GLuint> shadersGeometry = {vertexShaderGeometry, fragmentShaderGeometry};
m_glProgram[GEOMETRY] = compileProgram(shadersGeometry, ss);
glUseProgram(m_glProgram[GEOMETRY]);
m_glUniform[GEOMETRY_PROJECTION] = glGetUniformLocation(m_glProgram[GEOMETRY], "projection");   // Set in changeProjection(...)
m_glUniform[GEOMETRY_ORIENTATION] = glGetUniformLocation(m_glProgram[GEOMETRY], "orientation"); // Set in changeOrientation(...)
m_glUniform[GEOMETRY_MODE] = glGetUniformLocation(m_glProgram[GEOMETRY], "mode");               // Set here
m_glUniform[GEOMETRY_CHAR1] = glGetUniformLocation(m_glProgram[GEOMETRY], "char1");             // Set here
m_glUniform[GEOMETRY_SHANENESS] = glGetUniformLocation(m_glProgram[GEOMETRY], "shineness");     // Set here? For now it is hardcoded.
cleanProgram(m_glProgram[GEOMETRY], shadersGeometry);

if (m_glUniform[GEOMETRY_MODE] >= 0 && dim == 2)
{
    // TODO Add configuration for Poincare model.
    // For now, Beltrami-Klein is hardcoded.
    glUniform1i(m_glUniform[GEOMETRY_MODE], 1);
}
if (m_glUniform[GEOMETRY_CHAR1] >= 0)
{
    GLint char1[4];
    char1[0] = m_projected.chars(0);
    char1[1] = 1;
    char1[2] = m_projected.chars(1);
    char1[3] = m_projected.chars(1, 2);
    glUniform4iv(m_glUniform[GEOMETRY_CHAR1], 1, char1);
}
if (m_glUniform[GEOMETRY_SHANENESS] >= 0)
{
    // Add it to configuration. For now it is hardcoded.
    glUniform1f(m_glUniform[GEOMETRY_SHANENESS], 1.0);
}
////////////////////////////////////////////////////////
if (dim == 3)
{
    GLuint vertexShaderNew3d = compileShader(GL_VERTEX_SHADER, "vertex3d-new.glsl", ss);
    GLuint geometryShaderNew3d = compileShader(GL_GEOMETRY_SHADER, "geometry3d-new.glsl", ss);
    GLuint fragmentShaderNew3d = compileShader(GL_FRAGMENT_SHADER, "fragment3d-new.glsl", ss);
    m_glProgram[TRIANGLE] = compileProgram({vertexShaderNew3d, geometryShaderNew3d, fragmentShaderNew3d}, ss);
    glUseProgram(TRIANGLE);
    m_glUniform[PLANE_3D_PROJECTION] = glGetUniformLocation(m_glProgram[TRIANGLE], "projection");   // Set in changeProjection(...)
    m_glUniform[PLANE_3D_ORIENTATION] = glGetUniformLocation(m_glProgram[TRIANGLE], "orientation"); // Set in changeOrientation(...)
    m_glUniform[PLANE_3D_CHAR1] = glGetUniformLocation(m_glProgram[TRIANGLE], "char1");             // Set here
    m_glUniform[PLANE_3D_SHANENESS] = glGetUniformLocation(m_glProgram[TRIANGLE], "shineness");     // Set here? For now it is hardcoded.
    cout << "m_glProgram[PLANE_3D] = " << m_glProgram[TRIANGLE] << endl;
    cout << "m_glUniform[PLANE_3D_PROJECTION] = " << m_glUniform[PLANE_3D_PROJECTION] << endl;
    cout << "m_glUniform[PLANE_3D_ORIENTATION] = " << m_glUniform[PLANE_3D_ORIENTATION] << endl;
    cout << "m_glUniform[PLANE_3D_CHAR1] = " << m_glUniform[PLANE_3D_CHAR1] << endl;
    cout << "m_glUniform[PLANE_3D_SHANENESS] = " << m_glUniform[PLANE_3D_SHANENESS] << endl;
    if (m_glUniform[PLANE_3D_CHAR1] >= 0)
    {
        GLint char1[4];
        char1[0] = m_projected.chars(0);
        char1[1] = 1;
        char1[2] = m_projected.chars(1);
        char1[3] = m_projected.chars(1, 2);
        cout << "Before setting:       "; for (int i = 0; i < 4; i++) {cout << char1[i] << ' ';} cout << endl;
        glUniform4iv(m_glUniform[PLANE_3D_CHAR1], 1, char1);

        glGetUniformiv(m_glProgram[TRIANGLE], m_glUniform[PLANE_3D_CHAR1], char1);
        cout << "Read after setting:   "; for (int i = 0; i < 4; i++) {cout << char1[i] << ' ';} cout << endl;
        glGetUniformiv(m_glProgram[GEOMETRY], m_glUniform[GEOMETRY_CHAR1], char1);
        cout << "Similar for GEOMETRY: "; for (int i = 0; i < 4; i++) {cout << char1[i] << ' ';} cout << endl;
    }
    if (m_glUniform[PLANE_3D_SHANENESS] >= 0)
    {
        // Add it to configuration. For now it is hardcoded.
        glUniform1f(m_glUniform[PLANE_3D_SHANENESS], 1.0);
    }
}

По какой-то причине униформа ivec4 char1 установлена ​​правильно и может быть прочитана из первого шейдера с помощью m_glProgram[GEOMETRY] и униформы m_glUniform[GEOMETRY_CHAR1], но неправильно установлена ​​во втором шейдере с помощью m_glProgram[TRIANGLE] и униформы m_glUniform[PLANE_3D_CHAR1]. Выход этого кода:

m_glProgram[PLANE_3D] = 5
m_glUniform[PLANE_3D_PROJECTION] = 1262
m_glUniform[PLANE_3D_ORIENTATION] = 1261
m_glUniform[PLANE_3D_CHAR1] = 1263
m_glUniform[PLANE_3D_SHANENESS] = 1264
Before setting:       0 1 1 1 
Read after setting:   0 0 0 0 
Similar for GEOMETRY: 0 1 1 1 

Это означает, что подготовленный вектор [0, 1, 1, 1] правильно установлен в первом шейдере / программе, а не во втором. Запрос для его значения вернул значение по умолчанию [0, 0, 0, 0]. Что здесь не так?

1 Ответ

0 голосов
/ 03 сентября 2018

Если вы установили равномерную переменную с помощью glUniform4iv, то программа шейдера должна быть установлена ​​как часть текущего состояния рендеринга, потому что glUniform4iv устанавливает значение для стандартного унифицированного блока текущего шейдера программный объект. См. glUseProgram.

TRIANGLE - это индекс программного объекта шейдера, хранящийся в контейнере m_glProgram, но не собственный программный объект шейдера.

Это означает, что glUseProgram(TRIANGLE) не делает того, чего вы ожидаете.

Измените его на:

glUseProgram(m_glProgram[TRIANGLE]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...