Почему умножение матриц в шейдерах VERTEX не работает должным образом? - PullRequest
2 голосов
/ 29 апреля 2019

Я знакомлюсь с OpenGL в Visual Studio 2017. Следуя учебным пособиям www.learnopengl.com и пройдя контрольную точку текстур, преобразования сейчас являются основной проблемой.

Я отправляю свою модель, вид и перспективуматрицы для шейдера, используя предварительно полученный равномерный идентификатор местоположения, но при умножении матриц и вектора vec4(vertex, 1.0f) окно остается заполненным clearcolor.

Если умножить vec4(vertex, 1.0f) только на матрицу модели, объектрисуется (cube_flat.obj), но распространяется на весь видовой экран, поскольку перспектива и вид не учитываются.Что неправильно, но работает.

Код: main.cpp

int main()
{
    std::cout << "Application starting...\n" << std::endl;
    glm::ivec2 resolution = glm::ivec2(1280, 720);
    Window* window = new Window(resolution.x, resolution.y);

    SimpleMaterial* simpleMaterial = new SimpleMaterial();

    glFrontFace(GL_CCW);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);

    glm::mat4 projection = glm::perspective(glm::radians(60.0f), (float)resolution.x / (float)resolution.y, 0.1f, 1000.0f);
    glm::mat4 view = glm::inverse(glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -10.0f)));
    glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f));
    Mesh* mesh = Mesh::load("cube_flat.obj");

    // Render loop
    while (!window->shouldClose())
    {
        // Input
        window->processInput();

        // Rendering commands
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        // Tell OpenGL to use this Shader Program
        // Send attribute and uniform data to shader
        // Stream vertex, normal and uv data to shader
        simpleMaterial->render(projection, view, model, mesh);

        // Check & Call events
        window->poolEvents();
        // Swap buffers
        window->swapBuffers();
    }
    // Delete GLFW data
    delete window;
    return 0;
}

SimpleMaterial.cpp
SimpleMaterial::SimpleMaterial() : Material("simple")
{
    _vertex = _shader->getAttrib("vertex");
    _normal = _shader->getAttrib("normal");
    _uv = _shader->getAttrib("uv");

    _model = _shader->getUniform("model");
    _view = _shader->getUniform("view");
    _projection = _shader->getUniform("projection");
}

SimpleMaterial::~SimpleMaterial()
{
}

void SimpleMaterial::render(glm::mat4 pProjection, glm::mat4 pView, glm::mat4 pModel, Mesh* pMesh)
{
    _shader->use();
    glUniformMatrix4fv(_model, 1, GL_FALSE, glm::value_ptr(pModel));
    glUniformMatrix4fv(_view, 1, GL_FALSE, glm::value_ptr(pView));
    glUniformMatrix4fv(_projection, 1, GL_FALSE, glm::value_ptr(pProjection));

    pMesh->draw(_vertex, _normal, _uv);
}

simple.vs

#version 460

in vec3 vertex;
in vec3 normal;
in vec2 uv;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main(void) {
    gl_Position = projection * view * model * vec4(vertex, 1.0f);
}

simple.fs

#version 460

out vec4 fragment_color;

void main(void) {
    fragment_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}

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

1 Ответ

3 голосов
/ 29 апреля 2019

Настройка матрицы вида "неправильная".Направление обзора уходит в никуда.

glm::mat4 view = glm::inverse(glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -10.0f)));

Конечно, матрица вида является обратной матрицей этой матрицы, которая определяется позицией и направлением вида.
Система координат вида описывает направление и позицию, с которой просматривается сцена.Матрица вида преобразуется из мирового пространства в пространство вида (глаза).

Но система координат пространства просмотра OpenGL представляет собой правостороннюю систему, где ось X указывает навлево и ось Y указывает вверх.Это приводит к тому, что ось Z указывает вне поля зрения (обратите внимание, что ось Z является перекрестным произведением оси X и оси Y).
Фактически это поведение обусловлено матрицей проекции, которая определяетобъем просмотра и преобразование из пространства просмотра в пространство клипа (и далее нормализованное пространство устройства).

Это означает, что позиция просмотра должна быть glm::vec3(0.0f, 0.0f, 10.0f):

glm::mat4 view = glm::inverse(glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 10.0f)));
...