tutorial 중 중요한 부분 이므로 여러번 읽고 숙지하자.

Homogeneous coordinates

표현 3D vertices (x y, z, w) = >   
  • if w == 1 , position.
  • if w == 0 , direction.
중요한 내용 이므로 숙지


Code 표현 법

In C ++ , with GLM:


glm::mat4 myMatrix;

gim::vec4 myVector:

// ~ myMatrix, myVector  값 대입

glm::vec4 transformedVector = myMatrix * myVector:


In GLSL:


mat4 myMatrix;

vec4 myVector;

// ~ myMatrix, myVector  값 대입

vec 4 transformedVector = myMatrix * myVector;

Translation matrices

In C++, with GLM:

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


glm::mat4 myMatrix = glm::translate( 10.0f, 0.0f, 0.0f);

glm::vec4 myVector(10.0f, 10.0f, 10.0f, 0.0f);

glm::vec4 transformedVector = myMatrix * myVector;


In GLSL:


vec4 transformedVector = myMatrix * myVector;


The Identity matrix

In C++:
glm::mat 4 myIentityMatrix = glm::mat4(1.0f);


Scaling matrices

In C++ :

glm::mat4 myScalingMatrix = gl::scale(2.0f, 2.0f, 2.0f);


Rotation matrices

In C++ :
glm::vec3 myRotationAxis( ??, ??, ??);
glm::rotate( angle_in_degrees, myRotationAxixs );


Cumulating transformations

TransformedVector = TraslationMatrix * RotationMatrix * ScaleMatrix * OriginalVector;


계산순서 : Scale -> rotation -> translation -> Original


in C++ ,with GLM:

glm::mat4 myModelMatrix = myTranslationMatrix * myRotationMatrix * myScaleMatrix;

glm::vec4 myTrsformedVector = myModelMatrix* myOriginalVector;


in GLSL:

mat4 transform = nat2* mat1;

vec4 out+vec = transform * in_vec;


The Model, View and Projection matrices

이 부분 부터는 Blender 라는 프로그램을 이용한 3d 모델링 내용

좌표가 모델의 중심에 있는 모습


translation * rotation * scale 연산을 통해서 모델의 위치를 오른쪽으로 이동


이 경우 좌표가 World Space 단위로 바뀐다.


이미지에서 검정색 화살이 모델의 중심 좌표가 현재의 중심 (왼쪽의 vertices) 로 옮겨짐을 나타냄


이를 도표로 나타내면 


물체의 중심과 세계의 중심?? 이 일정한 상태에서 사용자의 시각만 변화는 모습


세계의 중심이 사용자의 시각에서 오른쪽으로 3단위 떨어져 있다면 사용자의 시각에서 왼쪽으로 3단위 떨어져 있는거나 마찬가지 이므로 

코드로 나타낸다면

glm::mat4 ViewMatrix = glm::translate(-3.0f, 0.0f, 0.0f);


이미지의 검은색 화살들이 중점의 변화를 나타내 준다.


이를 glm 함수를 사용하여 쓸 경우   

glm:mat4 CameraMatrix = glm::lookAt(

    cameraPositin,    //  world space에서 카메라의 위치 

    cameraTarget,    //  wordl space에서 볼 대상

    UpVector          //  vec3(0, 1, 0) 

}


위의 이미지를 도표로 나타낼 시

 



The Projection matrix


We’re now in Camera Space. This means that after all theses transformations, a vertex that happens to have x==0 and y==0 should be rendered at the center of the screen. But we can’t use only the x and y coordinates to determine where an object should be put on the screen : its distance to the camera (z) counts, too ! For two vertices with similar x and y coordinates, the vertex with the biggest z coordinate will be more on the center of the screen than the other.


이 부분은 정확한 해석이 되지 않음. 대략 x,y 만 사용하는게 아니라 z 축도 사용이되어서 z축이 매우 커질 경우 이를 중심으로 한다는 내용 같은데 확실치 않음.

 


이런 표현을 함수로 나타내면


glm::mat4 projectionMatrix = glm::perspective(

    FoV,                 //  Field of View, 90 ~ 30 

    4.0f / 3.0f,         //   측면 비율  화면 해상도에 의존  ( 4/3 == 800/600  == 1280/960)

    0.1f ,                //   Near Clipping plane , 가능한 크게

    100.0f              //    Far clipping plane , 가능한 작게

);

전체적인 흐름의 도표


튜토리얼에서 이 밑의 내용은 예시를 들은거 같은데 해석이 안되서 패스.......


Cumulating transformations : the ModelViewProjection matrix

//C++ : compute the matrix

glm::mat4 MVPmatrix = projection * view * model; // 역순임을 기억! 


//GLSL : 적용

transforemd_vertex = MVP * in_vertex;


Putting it all together


첫 단계 : MVP matrix 생성

// FOV 가 45도 이고 비율은 4:3 display 범위는 0.1 ~ 100 까지
glm::mat4 Projection = glm::perspective(glm::readans(45.0f), (float) width / (float)height, 0.1f, 100.0f);


glm::mat4 View = gl::lookAt(

    glm::vec3(4,3,3),            // 카메라 위치 , wordl space

    glm::vec3(0,0,0),            // 물체 중심 ,world space

    glm::vec3(0,1,0),            //Head is up 

);

// identitiy matrix

glm::mat4 Model = glm::mat4(1.0f);


glm::mat4 mvp = Projection * Vie * Model 


두번째 단계:  GLSL에 넘기기

// MVP에 대한 핸들 획득

// 단순히 초기화만

GLuint MatrixID = glGetUniformLocation(program_id,"MVP");

// MVP의 현재 bound shader 보냄

// main loop 에서 MVP가 바뀌기전에 일어나고 (최소한 M 이 바뀌기 전)

glUniformMtrix4fv(mvp_handle, 1, GL_FALSE ,&mvp[0][0]);

세번째 단계 : GLSL 작성

// vertex 값 입력, 매 실행 마다 다름

layout( location = 0 ) in vec3 vertexPosition_modelspace;


// 상수 값으로 존재하는 변수

uniform mat4 MVP;


void main(){

    //  cilp space 에서 vertex의 출력  ( MVP * position)

    gl_position = MVP  * vec4(vertexPosition_modelspace, 1);

}



신고

'컴퓨터 > OpenGL 4.3' 카테고리의 다른 글

tutorial 3 : matrices  (0) 2016.07.19
tutorial 2 : The first triangle  (0) 2016.07.18
toturial 1 : opening a window  (0) 2016.07.18
이 게시판 사용용도  (0) 2016.07.18

삼각형 그리기

이전의 tutorial 1 의 내용에서 glfwSetInputMode(~~) 밑 부분 부터  내용 추가 


//아직 까지 상세한 내용은 없고 추후 설명

window 생성후 OpenGL 을 호출하기전에 선언 및 호출

GLuint VertexArrayID ;

glGenVertexArrays(1,&VertexArrayID);

glBindVertexArray(VertexArrayID);


VAO( VertexArrayObject) 에 관한 내용이 있으나 중요하다 하지 않음.


Screen Coordinates

X : 오른쪽

Y : 위

Z : 앞뒤??



손가락 형태로 예시를 듬

X: 엄지손가락

Y: 집게손가락

Z: 중지


static const GLfloat g_vertex_buffer_data[]={

            -1.0f, -1.0f, 0.0f,

             1.0f, -1.0f, 0.0f,

             0.0f,  1.0f, 0.0f,

};

(-1 , -1) 왼쪽 아래

( 1, -1 ) 오른쪽 아래

( 0 , 1 ) 중앙 위


삼각형 그리기


//   버퍼 선언 

GLuint vertexbuffer

 //  1차워 버퍼 생성

glGenBuffers(1, &vertexbuffer);

// vertexbuffer 연결??

glBindBuffer(GL_ARRAY_BUFFER,vertexbuffer);

//위의 g_vertex_buffer_data 를 vertexbuffer 로 넘겨줌

glBufferData(GL_ARRAY_BUFFER,sizeof(g_vertex_buffer_data),g_vertex_buffer_data,GL_STATIC_DRAW);


do { }while 안의 내용


glEnableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

glVertexAttribPointer{

    0,                                        //attribute 0 , 0으로한 이유는 없으며 layout shader 값과 반드시 일치시켜줘야한다.

    3,                                        //size

    GL_FLOAT,                            //type

    GL_FALSE,                            //normalized?

    0,                                       //stride

    (void*)0                               // buffer offset

};

//도형 그리기

glDrawArrays(GL_TRIANGLES,0,3);// vertex 0 : 3 까지 vetices totla => 1 triagnle


glDisableVertexAttribArray(0);



Shader 

간단한 구성에서 2가지 Shader 사용 : Vertex , Fragment Shader

Shader는 GLSL이라는 Shader Language로 작성되어 있다.

GLSL은 런타임시 컴파일된다.

확장자명은 아무렇게나 txt , glsl 등


glsl같은경우 한번 불러와져서 앞으로 작성할 LoadShaders라는 코드의 상세 내용을 외울 필요는 없다.

사실상 glsl의 ID값으로 움직이고 LoadShaders는 가려진 상태이기때문에 숙지필요성이 떨어진다.


GLuint LoadShaders(const char* vertex_file_path, const char * fragment_file_path){


    //Shader 생성

    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);

    GLuint FragmentShader ID = glCreateShader(GL_FRAGMENT_SHADER);


    //file로 부터 Vertex_Shader 코드 읽음

    std::string VertexShaderCode;

    std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);

    if(VertexShaderStream.is_open()){

        std::string Line = "";

        while(getline(VertexShaderStream, Line))

            VertexShaderCode += "\n"+ Line;

        VertexShaderStream.close();

    }else{

        printf("Impossible to open%s. Are you in the right directory ? Don`t forget to read the FAQ !\n", vertex_file_path);

        getvhar();

  return 0;

    }


    //Fragment Shader 코드 읽기

    std::string FragmentShaderCode;

    std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);

    if(FragmentShaderStream.is_open()){

        std::string Line="";

        while(getline(FragmentShaderStream, Line))

            FragmentShaderCode += "\n" + Line;

        FragmentShaderStream.close();

    }


    GLint Result = GL_FALSE;

    int infoLogLnegth;


    //VertexShader 컴파일

    printf("Compilig shader : %s\n"  , vertex_file_path);

    char const * VertexSourcePointer = VertexShaderCode.c_str();

    glShaderSource(VertexShaderID , 1, &VertexSourcePointer , NULL);

    glCompileShader(VertexShaderID);


    // VertexShader 확인

    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS,&Result);

    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH,& InfoLogLength);

    if ( InfoLogLength > 0 ){

        std::vector<char> VertexShaderErrorMessage(InfoLogLength +1);

        glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);

        printf("%s\n",&VetexShaderErrorMessage[0]);

    }


    //FragmetShader 컴파일

    printf("Compilig shader : %s\n"  , fragment_file_path);

    char const * FragmentSourcePointer = FragmentShaderCode.c_str();

    glShaderSource(FragmentShaderID , 1, &FragmentSourcePointer , NULL);

    glCompileShader(FragmentShaderID);


    // FragmetShader 확인

    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS,&Result);

    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH,& InfoLogLength);

    if ( InfoLogLength > 0 ){

        std::vector<char> FragmentShaderErrorMessage(InfoLogLength +1);

        glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);

        printf("%s\n",&FragmentShaderErrorMessage[0]);

    }


    //Program 연결

    printf("Linking program\n");

    GLuint ProgramID = glCreateProgram();

    glAttachShader(ProgramID, VertexShaderID);

    glAttachShader(ProgramID, FragmetShaderID);

    glLinkProgram(ProgramID);

   

    //Program 검사

    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);

    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);

    if( InfoLogLength > 0 ){

        std::vector<char> ProgramErrorMessage(InfoLogLength+1);

        glGetProgramInfoLog(ProgramID, InfoLogLength,NULL, &ProgramErrorMessage[0]);

        printf("%s\n",&ProgramErrorMessage[0]);

    }


    glDetachShader(ProgramID, VertexShaderID);

    glDetachShader(ProgramID,FragmentShaderID);

    

    glDeleteShader(VertexShaderID);

    glDeleteShader(FragmentShaderID);


    return ProgramID;

}


Vertex Shader의 내용

첫줄은 컴파일러에게 어떤 버젼을 사용할지 알려줌

#version 330 core

둘때줄은 입력 값을 선언

layout(location = 0) in vec3 vertexPosition_modelspace;


vec3 : vector 3 in GLSL  glm::vec3 과 유사

layout(location =0 )  버퍼에게 vertexPosition_modelspace 특징을 사용한다고 알려준다.

  • 각각의 vertex가 많은 정보를 가짐 위치,여러 색, 물체의 좌표 등등, OpenGL은 뭘해야할지 모르기때문에

버퍼에게 뭘 사용할지 알려줘야하고  이런 것을 layout을 같은 값으로 설정함으로써 해결.

  • 0 외에 12까지 설정 가능
  • vertexPosition_modelspace 말고도 다른 이름 사용 가능



void main() {

    gl_Position.xyz = vertexPosition_modelspace;

    gl_Position.w=1.0;

}


Fragment Shader

#version 330 core
out vec3 color;
void main(){
    color = vec3(1,0,0);
}
//색깔 RGV 설정  == vec3(R,G,B);

삼각형 색 채우기

이전의 코드(Shader 코드 이전)에서  glBindVertexArray(VertexArrayID); 밑부분 부터
//programID 값 생성
GLuint programID = LoadShader("SimpleVertexShader.vertexshader",
                                "SimpleFragmentShader.fragmentshader");

mainloop 안에서 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BIT);

//설정한 Shader 사용  = > 삼각형 및 , 색 채움
glUseProgram(ProgramID);


신고

'컴퓨터 > OpenGL 4.3' 카테고리의 다른 글

tutorial 3 : matrices  (0) 2016.07.19
tutorial 2 : The first triangle  (0) 2016.07.18
toturial 1 : opening a window  (0) 2016.07.18
이 게시판 사용용도  (0) 2016.07.18
단순히 콘솔출력을 위한 헤더파일

#include<stdio.h>

#Include<stdlib.h>


glew 헤더파일 추가 아직까진 glew가 어떤 헤더파일인지는 생략 추후 설명

#include<GL/glew.h>



핸들하기 위해서 glfw 헤더파일 추가

#include<GL/glfw3.h>


3D그래픽 사용을위해 glm 추가 및  편의성을 위해 using namespace glm; 선언

#include<glm/glm.hpp>

using namespace glm;


---------------   메인 내용 ---------------------


GLFW 초기화 작업

if( !glfwInit() )

{

fprintf( stderr, "Failed to initialize GLFW\n" );

return -1;

}


GLFW 설정

glfwWindowHint(GLFW_SAMPLES, 4);

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);// 버전 설정 : 주요 버전

glfwWindowHint(GLFW_CONTEXT_VERSION_MINIOR, 3);//             :  서브 버전

glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);// 맥 사용자 전용??

glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);// OpenGL 구버전 사용 X



Window 생성 및 OpenGL 내용 생성

GLFWwindow* window = glfwCreateWindow(1024, 768, "Tutorial 01", NULL,NULL);    //Window 생성

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.1viersion of the tutorials.\n");

    glfwTerminate();

    return -1;

}


glfwMakeContextCurrent(window) // GLEW 초기화

glewExperimental = true; // core profile 에 필요   (core profile 이 뭘까 ?)

if(glewInit() != GLEW_OK){

    fprintf(stderr, "Failed to initalize GLEW\n");

    return -1;

}



window의 내용 변경 부분

glfwSetInputMode(window , GLFW_STICKY_KEYS, GL_TRUE);


do{

    glfwSwapBuffers(window);

    glfwPollEvents();

}while(glfwGetKey(window , GLFW_KEY_ESCAPE ) != GLFW_PRESS&& 

    glfwWindowShouldClose(window) == 0 );


전체적인 흐름 :  glfw 초기화및 생성  - > window 생성 -> GLEW 초기화 및 생성 -> window 변경 무한 루프 

신고

'컴퓨터 > OpenGL 4.3' 카테고리의 다른 글

tutorial 3 : matrices  (0) 2016.07.19
tutorial 2 : The first triangle  (0) 2016.07.18
toturial 1 : opening a window  (0) 2016.07.18
이 게시판 사용용도  (0) 2016.07.18

+ Recent posts

티스토리 툴바