Search code examples
c++openglgraphicsglslopengl-4

GLSL: Triangle disappears after multiplying with mat4


I am trying to learn OpenGl using this tutorial series. It all works fine up to tutorial 4 (Textures) but after tutorial 5 (3D Motion), the triangle which I have drawn previously disappears.

I have seen the video twice to make sure that I have not done any spelling mistake or something like this.

Code for relevant parts is given below:

main.cpp

#include <iostream>
#include <GL/glew.h>
#include <glm/glm.hpp>

#include "display.h"
#include "shader.h"
#include "mesh.h"
#include "texture.h"
#include "transform.h"


using namespace std;

int main()
{
    Display display(800, 600, "Hello World!");

    Vertex vertices[] = {
                         Vertex(glm::vec3(-0.5, -0.5, 0), glm::vec2(0.0, 0.0)),
                         Vertex(glm::vec3(0.5, -0.5, 0), glm::vec2(1.0, 0.0)),
                         Vertex(glm::vec3(0, 0.5, 0), glm::vec2(0.5, 1.0)),
                         };

    Mesh mesh(vertices, sizeof(vertices) / sizeof(vertices[0]));
    Shader shader("./res/basicShader");
    Texture texture("./res/bricks.jpg");
    Transform transform;

    while(!display.IsClosed())
    {
        display.Clear(0.0f, 0.1f, 0.3f, 1.0f);

        shader.Bind();
        texture.Bind(0);
        shader.Update(transform);
        mesh.Draw();

        display.Update();
    }
    return 0;
}

shader.h

#ifndef SHADER_H
#define SHADER_H

#include "transform.h"

#include <string>
#include <GL/glew.h>

class Shader
{
    public:
        Shader(const std::string& fileName);

        void Bind();
        void Update(const Transform& transform);
        virtual ~Shader();


    protected:

    private:
        static const unsigned int NUM_SHADERS = 2;
        Shader(const Shader& other){}
        //Shader& operator=(const Shader& other);
        void operator=(const Shader& other){}

        enum
        {
            TRANSFORM_U,

            NUM_UNIFORMS
        };

        GLuint m_program;
        GLuint m_shaders[NUM_SHADERS];
        GLuint m_uniforms[NUM_UNIFORMS];
};

#endif // SHADER_H

shader.cpp

#include "shader.h"

#include <iostream>
#include <fstream>
#include <string>

static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage);
static std::string LoadShader(const std::string& fileName);
static GLuint CreateShader(const std::string& text, GLenum shaderType);

Shader::Shader(const std::string& fileName)
{
    //ctor
    m_program = glCreateProgram();
    m_shaders[0] = CreateShader(LoadShader(fileName + ".vs"), GL_VERTEX_SHADER);
    m_shaders[1] = CreateShader(LoadShader(fileName + ".fs"), GL_FRAGMENT_SHADER);

    for(unsigned int i = 0; i<NUM_SHADERS; ++i)
        glAttachShader(m_program, m_shaders[i]);

    glBindAttribLocation(m_program, 0, "position");
    glBindAttribLocation(m_program, 1, "texCoord");

    glLinkProgram(m_program);
    CheckShaderError(m_program, GL_LINK_STATUS, true, "Error: Program linking failed: ");

    glValidateProgram(m_program);
    CheckShaderError(m_program, GL_VALIDATE_STATUS, true, "Error: Program is invalid: ");

    m_uniforms[TRANSFORM_U] = glGetUniformLocation(m_program, "transform");
}

Shader::~Shader()
{
    //dtor
    for(unsigned int i = 0; i<NUM_SHADERS; ++i)
    {
        glDetachShader(m_program, m_shaders[i]);
        glDeleteShader(m_shaders[i]);
    }

    glDeleteProgram(m_program);
}

static GLuint CreateShader(const std::string& text, GLenum shaderType)
{
    GLuint shader = glCreateShader(shaderType);

    if(shader == 0)
        std::cerr<<"Error: Shader creation failed!"<<std::endl;

    const GLchar* sourceShaderStrings[1];
    GLint sourceShaderStringLengths[1];

    sourceShaderStrings[0] = text.c_str();
    sourceShaderStringLengths[0] = text.length();

    glShaderSource(shader, 1, sourceShaderStrings, sourceShaderStringLengths);
    glCompileShader(shader);

    CheckShaderError(shader, GL_COMPILE_STATUS, false, "Error: Shader compilation failed: ");

    return shader;
}

static std::string LoadShader(const std::string& fileName)
{
    std::ifstream file;
    file.open(fileName.c_str());

    std::string output;
    std::string line;

    if(file.is_open())
    {
        while(file.good())
        {
            getline(file, line);
            output.append(line + "\n");
        }
    }
    else
    {
        std::cerr<<"Unable to load shader: "<<fileName<<std::endl;
    }

    return output;
}


static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage)
{
    GLint success = 0;
    GLchar error[1024] = {0};

    if(isProgram)
        glGetProgramiv(shader, flag, &success);
    else
        glGetShaderiv(shader, flag, &success);

    if(success == GL_FALSE)
    {
        if(isProgram)
            glGetProgramInfoLog(shader, sizeof(error), NULL, error);
        else
            glGetShaderInfoLog(shader, sizeof(error), NULL, error);

        std::cerr<<errorMessage<<": '"<<error<<"' "<<std::endl;
    }
}


void Shader::Bind()
{
    glUseProgram(m_program);
}


void Shader::Update(const Transform& transform)
{
    glm::mat4 model = transform.GetModel();

    glUniformMatrix4fv(m_uniforms[TRANSFORM_U], 1, GL_FALSE, &model[0][0]);

}

transform.h

#ifndef TRANSFORM_H
#define TRANSFORM_H

#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>

class Transform
{
    public:
        Transform(const glm::vec3& pos = glm::vec3(), const glm::vec3& rot = glm::vec3(), const glm::vec3& scale = glm::vec3(1.0f, 1.0f, 1.0f)):
        m_pos(pos),
        m_rot(rot),
        m_scale(scale)
        {

        }

        inline glm::mat4 GetModel() const
        {
            glm::mat4 posMatrix = glm::translate(m_pos);
            glm::mat4 rotXMatrix = glm::rotate(m_rot.x, glm::vec3(1, 0, 0));
            glm::mat4 rotYMatrix = glm::rotate(m_rot.y, glm::vec3(0, 1, 0));
            glm::mat4 rotZMatrix = glm::rotate(m_rot.z, glm::vec3(0, 0, 1));
            glm::mat4 scaleMatrix = glm::scale(m_rot);

            glm::mat4 rotMatrix = rotZMatrix * rotYMatrix * rotXMatrix;

            return posMatrix * rotMatrix * scaleMatrix;
        }

        inline glm::vec3& GetPos(){return m_pos;}
        inline glm::vec3& GetRot(){return m_rot;}
        inline glm::vec3& GetScale(){return m_scale;}

        inline void SetPos(const glm::vec3& pos){m_pos = pos;}
        inline void SetRot(const glm::vec3& rot){m_rot = rot;}
        inline void SetScale(const glm::vec3& scale){m_scale = scale;}

        virtual ~Transform();


    protected:

    private:
        Transform(const Transform& other){}
        void operator=(const Transform& other){}

        glm::vec3 m_pos;
        glm::vec3 m_rot;
        glm::vec3 m_scale;
};

#endif // TRANSFORM_H

Vertex Shader Filename: basicShader.vs

#version 120

attribute vec3 position;
attribute vec2 texCoord;

varying vec2 texCoord0;

uniform mat4 transform;

void main()
{
    //gl_Position = vec4(position, 1.0); // #1
    gl_Position = transform * vec4(position, 1.0); // #2
    // if I uncomment Statement #1 and put comment on #2, it works obviously I can not move the triangle.
    texCoord0 = texCoord;
}

Frangment Shader Filename: basicShader.fs

#version 120

uniform sampler2D diffuse;

varying vec2 texCoord0;

void main()
{
    gl_FragColor = texture2D(diffuse, texCoord0); //vec2(0.2, 0.2)); //vec4(1.0, 0.0, 0.0, 1.0);
}

Solution

  • You use your rot vector to define your scale matrix.

    glm::mat4 scaleMatrix = glm::scale(m_rot);

    you should use your scale vector

    glm::mat4 scaleMatrix = glm::scale(m_scale);
    

    You were scalling by a 0 which set your point all of your point to the (0,0,0) position, they will collide and your face disapear