상세 컨텐츠

본문 제목

OpenGL Viewing - Viewing, Modeling, Projection, Viewport transformation

프로그래밍 관련/3D,2D DRAW 관련

by AlrepondTech 2017. 8. 18. 17:21

본문

반응형



OpenGL을 쓰고 항시 API를 쓰고 다시 해제해주어야 하는 API들은 는 해제 해주는것을 잊지 마세요 

예로들어 wglMakeCurrent(...)로 들자면 


HDC   hdc    = getHDC();

HGLRC hglrc = getHGLRCRES_GL();


::wglMakeCurrent(hdc, hglrc); //사용


///////////////////////////////////////////////////////////
//{랜더링 코드들

..................................................................

//}
///////////////////////////////////////////////////////////

::wglMakeCurrent(NULL, NULL);  //::wglMakeCurrent(hdc, NULL);  //해제



위와같이 wglMakeCurrent(...) 랜더링 부분에 Api 사용과 해제 부분을 제대로 하지 않으면 다른 

위치의 wglMakeCurrent(...) 를 사용시 문제가 생길수 있습니다.



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




출처: http://diehard98.tistory.com/m/entry/OpenGL-Viewing-Viewing-Modeling-Projection-Viewport-transformation



OpenGL에서 어쩌면 가장 중요한 부분이 바로 Viewing 이 아닌가 싶다. 이 파트는 어떻게 보여지는 가를 설정하는 모든 명령에 관련되어 있는데 이걸 못하면 아무리 멎진 그림을 그려놔도 볼수가 없으니 말이다.


Red Book을 보면 참 설명이 잘 되어 있는데 문제는 영어로 되어 있다. -_-; 암튼, Red Book을 근거로 하여 설명하자면 OpenGL에서 Viewing을 설정하는 것은 카메라로 사진을 찍는 것과 유사하다고 말한다.



옆의 그림이 그것을 설명하는데 우선 차례 차례 보자. 제일 먼저 해야 하는 것이 카메라 설치이다. 이것은 첫번째 그림이 의미하는 바인데 OpenGL에서는 이것을 Viewing Transformation 이라고 한다. 

두번째로 해야 할 일은 사진찍을 물체를 적당한 위치에 놓는 것이다. (두번째 그림) 이것을 OpenGL에서는 Modeling Transformation 이라고 한다. 

세번째는 적당한 렌즈로 초점을 맞추는 일이다. OpenGL에서는 이 과정을 Projection Transformation 이라고 한다. 사실 이 파트의 설명은 조금 어색하긴 하다. OpenGL에서 이 과정은 사실 '잘라내기'에 가깝다. 왜냐면 이 과정에서 보여질 깊이를 설정하여 필요없는 부분은 잘라내 버리기 때문이다. 물론 카메라의 초점 조절이 어떤 깊이에 있는 물체를 '깨끗하게' 잡을 것인가를 정의한다는 면에서 비슷하기는 하지만 '잘라내기'를 하지 않는다는 점에서 조금 다르다. 

마지막으로 네번째가 '현상하기'인데 OpenGL에서의 사진 현상은 모니터에 그려내기와 같다. 이 과정을 Viewport Transformation 이라고 한다. 

이 일련의 과정들에서 주의해야 할 것들이 몇가지 있다. 

1. Viewing Transformation은 반드시 Modeling Transformation 보다 우선적으로 선언되어야 한다. 이 말은 카메라를 먼저 놓고 물체를 그리라는 말인데 정확한 이유는 설명되어 있지 않지만 내 생각에는 물체를 옮기고 변형하는 과정에서 계산된 매트릭스가 카메라를 놓는 Viewing Transformation에 영향을 미치면 예상치 못한 결과가 나올수 있기 때문이 아닐까 싶다. 상식적으로 생각해도 카메라를 먼저 놓고 물체를 놓는게 OpenGL의 세계에서는 합당한듯 하다. 

2. 뭔가를 그리기 전에는 항상 glLoadIdentity() 함수로 현재의 매트릭스를 초기화 한다. 이것은 매우 중요한 부분인데 먼저 이해해야 할 것이 OpenGL은 똑똑하지 않다. 렌더링 과정에서 사용되는 매트릭스가 있는데 이 매트릭스는 C의 static 과 같은 속성을 가진다. 즉, 한번 초기화된 후 사용자가 다른 값을 넣으면 계속 그 값을 유지하게 된다는 것이다. 렌더링을 할때 마다 그 값이 초기화 되지 않고 이전의 값을 유지하므로 적절한 시기에 초기화 하지 않으면 앞에서 계산된 값이 계속 적용되어 완전 예상 밖의 결과가 나온다. 고로 매번의 렌더링 마다 적절한 곳에서 초기화가 필요하다.

3. glMatrixMode() 함수를 이용하여 매트릭스 선택하기. 앞서 2번에서 말한 렌더링 과정에 사용되는 매트릭스는 두 가지가 존재한다. 하나는 GL_MODELVIEW고 다른 하나는 GL_PROJECTION 이다. GL_MODELVIEW는 Modeling Transformation과 Viewing Transformation에 관련된 매트릭스라는 의미고 GL_PROJECTION은 Projection Transformation에 관련된 매트릭스라는 의미다. glMatrixMode() 함수에 GL_MODELVIEW 인자를 넣게 되면 Modeling Transformation과 Viewing Transformation에 관련된 연산을 하는 매트릭스를 현재의 매트릭스로 선택하라는 의미고 마찬가지로 GL_PROJECTION 은 Projection Transformation에 관한 매트릭스를 현재의 매트릭스로 선택하라는 의미다. 

참 답답하게도 OpenGL은 현재의 매트릭스를 하나만 정해 사용할 수 있는 고집쟁이다. (아마도 최고의 스피드를 내기 위해 그런듯) 그래서 위의 명령을 이용해 다음 명령들에 의해 영향을 받을 매트릭스를 지정해 준다. 고로, glMatrixMode(GL_MODELVIEW)를 호출한 다음 glLoadIdentity()를 호출하면 물체를 놓고 움직이는 것에 관련된 매트릭스를 초기화하게 되는 것이다.

이제 Red Book에 나오는 예제를 이용해서 설명을 해보겠다.

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glLoadIdentity();         // 6. 매트릭스 초기화

/* Modeling Transformation & Viewing Transformation */
gluLookat(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);  // 7. Viewing Transformation
glScalef(1.0, 2.0, 1.0);                                        // 8. Modeling Transformation
glutWireCube(1.0);                                            // 9. 렌더링
glFlush();
}

void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);             // 1. Viewport Transformation
glMatrixMode(GL_PROJECTION);                        // 2. GL_PROJECTION 매트릭스 선택
glLoadIdentity();                                                // 3. 매트릭스 초기화
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);               // 4. Projection Transformation 
glMatrixMode(GL_MODELVIEW);                         // 5. GL_MODELVIEW 매트릭스 선택
}

위의 코드는 일부만 나타낸 것이지만 렌더링에 관련된 모든 부분이다. 번호가 매겨진 순서대로 렌더링이 일어난다고 생각하면 된다. reshape 함수는 최초 윈도우 생성시 및 윈도우 크기 변경등이 발생할때 호출되는 함수로 우선적으로 호출된다고 보면 된다.

제일 먼제 Viewport Transformation을 통해 보여질 화면을 스크린의 좌표계에서 어디서 어디까지인지 정의하였다. 이 함수는 매우 간단하다. 현재 나의 스크린이 1024 x 768이라고 하고 이 모든 영역에 OpenGL 렌더링을 하고 싶다면 걍 glViewport(0, 0, 1024, 768) 하면 그만이다. 입력으로 들어오는 w와 h값을 이용하는데 이것은 일반적인 프로그래밍의 경우 새로 변경된 윈도우의 크기가 될 가능성이 매우 높다. 

2번에서 GL_PROJECTION 매트릭스를 선택했다. 그리고 바로 3번에서 초기화 했고 (이전의 값 삭제) 4번에서 glFrustum() 함수를 이용해서 렌즈조절 (보여질 영역설정)을 했다. 이 함수는 perspective transformation을 하는데 원근법에 따라 멀리 있는 물체를 작게 보여준다는 의미다. 이와 반대로 직교법 (Orthographic transformation)을 이용하는 함수는 glOrtho() 함수가 있다. 

그리고 탈출하기 전에 선택된 매트릭스를 GL_MODELVIEW로 변경시켰다. 이제 다음은 직접적인 렌더링을 하는 함수인 display 함수이다. 우선 6번을 통해 선택된 GL_MODELVIEW 매트릭스를 초기화 시키고 7번을 통해 카메라를 위치시키는 Viewing Transformation을 수행한다. gluLookAt( 눈의 위치 (x,y,z), 쳐다볼 위치(x,y,z), 카메라 위쪽 방향 (x,y,z))를 이용해 아주 간단하게 카메라를 위치시킨다. 그리고 8번은 물체를 그릴때 적용될 Transformation을 정의한 것인데 y 축방향의 좌표는 2배로 적용될 것이라는 의미다. 그리고 나서 렌더링에 들어간다...

쓰다보니 좀 부족한 설명이 있는데 각 함수들에 대한 설명은 OpenGL 매뉴얼이나 검색을 하면 쉽게 얻을 수 있어서 생략했다. 이런 과정을 통해서 렌더링이 일어난다는 것만 설명했다. 아무래도 가장 중요한건 OpenGL의 상태 변수는 Static 속성을 가진다는 것이 아닐까 싶다... 디버깅 프로그램을 이용해 현재 무슨 값을 가지는지 쉽게 볼 수 있다면 이것이 그리 중요하지 않을지 모르나 OpenGL에서는 현재의 상태를 확인하기 위해서는 별도의 함수를 매번 호출해야 하므로 쉽게 확인이 불가능하다. 고로 보여지지 않으므로 무슨 일이 벌어지는지 알기 어렵다. 그래서 새까만 화면이 나오더라도 뭐가 잘못된건지 알수가 없는 경우가 허다하다.


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

반응형


관련글 더보기

댓글 영역