갬장장이
[OpenGL] 12. Model View Projection Matrices
갬장장이
갬장장이의 코드 대장간
갬장장이
전체
오늘
어제
  • 분류 전체보기 (216)
    • 게임 연구소 (6)
    • 게임 제작 (15)
      • We need more guns (2024~) (1)
      • Rovenhell (2023) (2)
      • Geophyte (2020~2021) (5)
      • 아드레날린 러시 (2021) (2)
      • Treadmill (2019) (1)
      • 습작들 (2019~) (2)
      • 그 외 (~2018) (2)
    • mathematics (33)
      • game mathematics (30)
      • linear algebra (3)
    • networking (3)
    • computer graphics (46)
      • 3D Graphics (23)
      • DirectX (8)
      • OpenGL (13)
      • graphics theory (2)
    • game engines (10)
      • Unity (0)
      • Unreal Engine (10)
    • os (6)
      • Linux (0)
      • operating system (1)
      • multithreading, parallel co.. (5)
    • lang (34)
      • c++ (15)
      • .NET (5)
      • python (1)
      • java (3)
      • erlang, elixir (1)
      • js, ts (7)
    • software engineering (47)
      • PS (25)
      • algorithms (15)
      • data structures (2)
      • design patterns (4)
    • cs (4)
    • database (2)
      • SQL (1)
    • web (6)
      • web (3)
      • frameworks, libraries (3)
    • finance (0)
    • 음악 제작 (1)
    • life (3)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

  • [공지] 블로그 안내

인기 글

최근 댓글

최근 글

hELLO · Designed By 정상우.
computer graphics/OpenGL

[OpenGL] 12. Model View Projection Matrices

2022. 5. 3. 12:57

Model, View, Projection Matrix들은 최종적으로 어떤 vertex가 화면 상의 어느 픽셀에 위치해야 하는지를 결정할 때 사용되는 행렬들이며, 이 행렬들을 서로 곱해 4x4 크기의 MVP matrix를 만들어 사용한다. 이렇게 구한 행렬을 vertex position과 곱해 화면 상의 위치를 구할 수 있다.

 

Projection Matrix는 지난 시간에도 잠시 다뤘지만, 어떠한 3차원 공간을 2차원 상의 공간에 맵핑하는(=투영) 역할을 해 준다. 카메라와 거리가 0인 물체는 x, y 좌표를 3차원 공간일 때의 값 그대로 유지하겠지만, 멀리 있는 물체는 같은 x, y 좌표에 있더라도 z값이 크기 때문에 맵핑 후에는 x, y 값이 변하는데, 이를 하나의 행렬곱으로 표현할 때 사용되는 행렬이다.

참고하면 좋은 글: https://jw910911.tistory.com/19

 

그래픽스 - Projection Matrix란?

투영행렬과 뷰행렬의 관계 뷰 행렬(View Matrix)란 랜더링 파이프라인 단계의 3번째 단계인 뷰 스페이스를 구성하는데 사용되는 설정을 위한 행렬이라고 한다면 투영 행렬은 파이프라인 단계의 투

jw910911.tistory.com

 

View Matrix는 카메라의 위치(시점)을 나타낼 때 사용되는 행렬이며,

Model Matrix는 오브젝트의 Transform을 나타내는 행렬이다. (=TRS Matrix로 이해하면 된다)

 

주의해야 할 것은, 카메라를 이동시키는 건 결국 나머지 모든 오브젝트들을 반대로 이동시키는 것과 동일하다는 것이다. 즉 중요한 것은 오브젝트와 카메라의 상대적 관계이지, 카메라의 절대적 위치가 아니다.

 

코드와 함께 살펴보자.

Application.cpp

// Include GLEW
#include <GL/glew.h>

// Include GLFW
#include <GLFW/glfw3.h>

#include <iostream>

#include "VertexBuffer.h"
#include "VertexArray.h"
#include "IndexBuffer.h"
#include "Shader.h"
#include "Renderer.h"
#include "Texture.h"

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

GLFWwindow* InitWindow()
{
    // Initialise GLFW
    if( !glfwInit() )
    {
        fprintf( stderr, "Failed to initialize GLFW\n" );
        getchar();
        return nullptr;
    }

    glfwWindowHint(GLFW_SAMPLES, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // Open a window and create its OpenGL context
    GLFWwindow* window = glfwCreateWindow( 960, 540, "Tutorial 02 - Red triangle", NULL, NULL);
    if( window == NULL ){
        fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
        getchar();
        glfwTerminate();
        return nullptr;

    }
    glfwMakeContextCurrent(window);

    // Initialize GLEW
    glewExperimental = true; // Needed for core profile
    if (glewInit() != GLEW_OK) {
        fprintf(stderr, "Failed to initialize GLEW\n");
        getchar();
        glfwTerminate();
        return nullptr;
    }

    std::cout << "Using GL Version: " << glGetString(GL_VERSION) << std::endl;

    // Ensure we can capture the escape key being pressed below
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);

    return window;
}

int main( void )
{
    GLFWwindow* window = InitWindow();
    if (!window)
        return -1;

    float positions[] = {
        100.0f, 100.0f, 0.0f, 0.0f, // 0
        200.0f, 100.0f, 1.0f, 0.0f, // 1
        200.0f, 200.0f, 1.0f, 1.0f, // 2
        100.0f, 200.0f, 0.0f, 1.0f  // 3
    };

    unsigned int indices[] = {
        0, 1, 2,
        2, 3, 0
    };

    GLCall( glEnable(GL_BLEND) );
    GLCall( glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) );

    {
        VertexArray va;
        VertexBuffer vb(positions, 4 * 4 * sizeof(float));
        IndexBuffer ib(indices, 6);

        glm::mat4 proj = glm::ortho(0.0f, 960.0f, 0.0f, 540.0f, -1.0f, 1.0f);

        glm::mat4 ident = glm::mat4(1.0f);
        /*
        레퍼런스 참고:
        5.4.2 Vector and Matrix Constructors
        If there is a single scalar parameter to a matrix constructor, 
        it is used to initialize all the components on the matrix's diagonal, 
        with the remaining components initialized to 0.0.
        간단히 말해 위 코드는 4x4짜리 Identity Matrix를 만드는 코드임.
        */
        glm::vec3 trvec = glm::vec3(-100, 0, 0); // translation vector, x축으로 -100만큼 이동
        glm::mat4 view = glm::translate(ident, trvec); // Translation matrix를 만든다. ([Mathematics] 11. Translation 글 참고)
        glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(200, 200, 0)); // 마찬가지로 translation matrix를 만들되, 오브젝트를 x,y축으로 모두 200씩 이동시킨다.

		/*
        Model matrix와 view matrix는 결국 둘다 해주는 일은 같다. (수학적 원리는 동일하다)
        또한 본 예제에서는 translation matrix만 사용했지만 Rotation과 Scalining을 모두 곱해 TRS Matrix 형태를 사용해도 된다.
        */

        glm::mat4 mvp = proj * view * model;
        // 곱하는 순서가 PVM순인걸 알 수 있는데, 이는 행렬곱 특성상 P*(V*M) 순으로 진행되기에 결국은 MVP순으로 곱이 계산되기 때문이다.
		// 주의) TRS Matrix는 MVP와 다르게 이름 순서와 똑같이 T*(R*S) 순으로 곱해준다

        // projection matrix
        // view matrix
        // model matrix

        VertexBufferLayout layout;
        layout.AddFloat(2);
        layout.AddFloat(2);

        va.AddBuffer(vb, layout);

        Shader shader("res/shaders/Basic.shader");
        shader.Bind();
        shader.SetUniform4f("u_Color", 0.0f, 0.3f, 0.8f, 1.0f);
        shader.SetUniformMat4f("u_MVP", mvp);

        Texture texture("res/textures/phone.png");
        texture.Bind();
        shader.SetUniform1i("u_Texture", 0);

        float red = 0.0f;
        float step = 0.05f;

        Renderer renderer;

        do {
            renderer.Clear();

            shader.Bind();
            shader.SetUniform4f("u_Color", red, 0.3, 0.8, 1.0);

            renderer.Draw(va, ib, shader);

            // Swap buffers
            glfwSwapBuffers(window);
            glfwPollEvents();

            // increment red
            if (red < 0.0f || red > 1.0f)
                step *= -1.0;
            red += step;

        } // Check if the ESC key was pressed or the window was closed
        while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
                glfwWindowShouldClose(window) == 0 );
    }

    // Close OpenGL window and terminate GLFW
    glfwTerminate();

    return 0;
}

 

 

 

저작자표시 비영리 변경금지

'computer graphics > OpenGL' 카테고리의 다른 글

[OpenGL] 11. OpenGL과 수학  (0) 2022.04.16
[OpenGL] 10. Blending  (0) 2022.04.16
[OpenGL] 9. Textures  (0) 2022.04.09
[OpenGL] 8. 추상화(Abstraction)와 렌더러  (0) 2022.04.02
[OpenGL] 7. Vertex Array Object (VAO)  (0) 2022.03.01
'computer graphics/OpenGL' 카테고리의 다른 글
  • [OpenGL] 11. OpenGL과 수학
  • [OpenGL] 10. Blending
  • [OpenGL] 9. Textures
  • [OpenGL] 8. 추상화(Abstraction)와 렌더러
갬장장이
갬장장이
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.