Marian Baňas
Marian Baňas

Reputation: 23

Why wont matrix multiplication in VERTEX shader work properly?

I am getting to know OpenGL in Visual Studio 2017. Following www.learnopengl.com tutorials and got past the textures checkpoint, transformations being the main problem right now.

I send my model, view and perspective matrices to the shader, using the preacquired uniform location id, but when multiplying the matrices and vec4(vertex, 1.0f) vector, the window stays filled with clearcolor.

If I multiply the vec4(vertex, 1.0f) only with model matrix, the object is drawn (cube_flat.obj) but is spread over the whole viewport, since perspective and view is not taken into consideration. Which is wrong, but works.

Code: 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);
}

I expect a cube viewed from perspective instead of nothing / cube spread over the viewport due to no perspective and view transformation.

Upvotes: 2

Views: 584

Answers (1)

Rabbid76
Rabbid76

Reputation: 210928

The setup of the view matrix is "wrong". The direction of view goes to nowhere.

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

Of course, the view matrix is the inverse matrix of that matrix, which is defined by the view position and direction.
The view coordinates system describes the direction and position from which the scene is looked at. The view matrix transforms from the world space to the view (eye) space.

But the OpenGL view space coordinate system is a Right-handed system, where the X-axis points to the left and the Y-axis points up. This causes that the Z-axis points out of the view (Note the Z-Axis is the cross product of the X-Axis and the Y-Axis).
In fact this behavior is caused by the projection matrix, which defines the view volume and transformation from view space to clip space (and further normalized device space).

This means the view position has to be 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)));

Upvotes: 3

Related Questions