Унифицированный mat4 имеет неизвестные значения при создании glUniformMatrix4fv - PullRequest
0 голосов
/ 27 января 2019

У меня есть очень простой движок, основанный на OpenGL, который может рендерить многоугольники любого цвета в окно с изменяемыми размерами.Сейчас я пытаюсь реализовать матрицы для своих шейдеров, передавая матрицы модели, перспективы и представления в виде униформы через мой шейдер.Перед добавлением униформы все работало как надо, я мог даже передать униформу vec2 для имитации источника света в положении моей мыши.Унифицированные mat4 s не работают так же хорошо, как vec2 s.

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

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

Этокак выглядит мой вершинный шейдер:

#version 430 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec4 color;

out vec4 Color;

uniform mat4 model;
uniform mat4 view;
uniform mat4 project;

void main()
{
    mat4 id;
    id[0] = vec4(1.0, 0.0, 0.0, 0.0);
    id[1] = vec4(0.0, 1.0, 0.0, 0.0);
    id[2] = vec4(0.0, 0.0, 1.0, 0.0);
    id[3] = vec4(0.0, 0.0, 0.0, 1.0);
    Color = color;
    gl_Position = id * vec4(position, 1.0);
}

mat4 id - это вручную созданная единичная матрица, при изменении id * на model * я получаю черное окно.

Вот какмой фрагментный шейдер выглядит так:

#version 430 core

in vec4 Color;

out vec4 outColor;

void main()
{
    outColor = Color;
}

Шейдер инициализируется этим кодом:

m_shaderID = glCreateProgram();

const char* vertexSource = ReadFile::readFile(vertpath);
const char* fragmentSource = ReadFile::readFile(fragpath);

GLint status;

// Vertex Shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE)
{
    std::cout << "Failed to compile vertex shader!\nInfo log: " << std::endl;
    char buffer[512];
    glGetShaderInfoLog(vertexShader, 512, NULL, buffer);
    std::cout << buffer << std::endl;
    glDeleteShader(vertexShader);
}

// Fragment Shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE)
{
    std::cout << "Failed to compile fragment shader!\nInfo log: " << std::endl;
    char buffer[512];
    glGetShaderInfoLog(fragmentShader, 512, NULL, buffer);
    std::cout << buffer << std::endl;
    glDeleteShader(fragmentShader);
}

// Shader program
glAttachShader(m_shaderID, vertexShader);
glAttachShader(m_shaderID, fragmentShader);
glLinkProgram(m_shaderID);
glValidateProgram(m_shaderID);

glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);

Матрица создается как единое целое с помощью этого кода:

void Shader::setUniformmat4(const GLchar* name, glm::mat4 matrix)
{
    for (int i = 0; i <= 3; i++)
        printf("%f, %f, %f, %f\n", matrix[i].x, matrix[i].y, matrix[i].z, matrix[i].w);
    glUniformMatrix4fv(glGetUniformLocation(m_shaderID, name), 1, GL_FALSE, glm::value_ptr(matrix));
}

printf предназначен для проверки значений матрицы, так как они используются для создания униформы, и они имеют значения единичной матрицы в этой точке.

Функция setUniformmat4 вызывается этимкод:

glm::mat4 model = glm::mat4(1.0);
shader.setUniformmat4("model", model);

При создании светового эффекта я создаю униформу, вызывая эту функцию:

void Shader::setUniformvec2(const GLchar* name, glm::vec2 vector)
{
    glUniform2f(glGetUniformLocation(m_shaderID, name), vector.x, vector.y);
}

через этот фрагмент кода:

shader.setUniformvec2("light_pos", glm::vec2((x / window.getWidth()) * 2.0 - 1.0, 1.0 - 2.0 * (y / window.getHeight())));

Гдеx и y - координаты мышки.Затем я добавляю строку

uniform vec2 light_pos;

к фрагментному шейдеру.Это работает без проблем и отлично отслеживает мышь.Функция, используемая для установки униформы mat4, выглядит так же, как и функция для установки униформы vec2, разница только в 4fv для mat4 и 2f для vec2.

.видите, я использую glm для матриц и векторов.

Моя основная функция выглядит следующим образом:

    Window window(720, 720, "Window");

    Shader shader("shader.vert", "shader.frag");

    glm::mat4 model = glm::mat4(1.0);
    shader.setUniformmat4("model", model);

    Renderer* renderer = new Renderer();

    std::vector<StaticSprite*> sprites;

    sprites.push_back(new StaticSprite(-0.5, -0.5, 0.0, 1.0, 1.0, glm::vec4(1.0, 1.0, 0.0, 1.0), &shader));

    while (!window.closed())
    {
        window.clear();
        shader.enable();
        double x, y;
        window.getMousePosition(x, y);
        shader.setUniformvec2("light_pos", glm::vec2((x / window.getWidth()) * 2.0 - 1.0, 1.0 - 2.0 * (y / window.getHeight())));

        for (StaticSprite* sprite : sprites)
            renderer->submit(sprite);
        renderer->flush();

        shader.disable();
        window.update();
    }
    return 0;

В целом мой вопрос сводится к тому, почему значения единого mat4 неправильно, есть ли способ узнать, что это за значения, и что я должен изменить в коде, чтобы заставить работать единообразный mat4s?

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

1 Ответ

0 голосов
/ 27 января 2019

glUniform* укажите значение единой переменной для текущего программного объекта.Это означает, что программа должна быть установлена ​​glUseProgram до:

Shader shader("shader.vert", "shader.frag");

shader.enable(); // <--- this is missing

glm::mat4 model = glm::mat4(1.0);
shader.setUniformmat4("model", model);

Активные программные ресурсы можно получить из объекта программы, который не является "текущей" программой (например, glGetUniformLocation).Обратите внимание, что программный объект является параметром glGetUniformLocation.
Но чтобы установить значение униформы на glUniform*, программа должна быть текущей установленной программой.

...