[ OpenGL 4 ] Culling, GL_ARRAY, GL_PROJECTION
OpenGL 로 육면체를 그리는 코드를 분석해보면서 기본 함수들을 배워보도록 하겠다.
MyVertices 는 정육면체의 정점의 배열로 이뤄져있다. 각 원소는 당연히 정점의 (x,y,z) 성분이다. MyColors 는 정육면체 Color를 설정할 RGB 성분의 배열이고 MyVertexList는 정점의 번호-MyVertices의 인덱스 순서가 정점의 번호이다-를 나열했는데, 이는 이 정점들을 순서데로 그려서 면을 나타낼 것이기 때문이다. 본문을 보도록 하겠다.
glFrontFace(mode) 함수는 와인딩을 설정하는 함수이다. 와인딩이란 정점이 연결되는 방향을 의미하는데 이 함수의 인자로는 GL_CCW GL_CW 두가지가 있다. 그림으로 살펴보자.
*ccw : count clock wise
*cw : clock wisw
어느방향으로 가든 똑같은 삼각형이다그렇다면 이 정점을 잇는 순서가 무슨 의미가 있을까? GL에서는 이 순서로 면의 앞과 뒤를 결정한다. GL에서는 디폴트로 반시계 방향으로 돌았을때 앞면으로 간주된다. 인자로 GL_CW 를 전달한다면 시계방향을 정면으로 설정한다.
그렇다면 다시 면의 앞과 뒤를 설정하는 것이 무슨 의미가 있을까?
culling 이란 그래픽최적화를 위해 사용자가 화면에서 보는 면 말고 안보이는 뒷면을 출력하지 않는 것으로 부하를 줄이는 것을 의미한다.

햄버거를 위에서 본다고 상상해보자 대부분 빵밖에 안보이겠지만 실제로는 참깨빵 위에 순쇠고기 패티두장 특별한 소스 양상추 치즈 피클 양파까지 있다 그런데 고기와 양배추를 전부 출력하는 것은 의미가 없기 때문에 이를 출력하지 않으므로, 그래픽 부하를 줄일 수 있다. 이것으 컬링 이라 하며, glEnable(GL_CULL_FACE) 는 후면제거 컬링 모드를 활성화 한다는 의미이다.
따라서 위 프로그램은 CCW 와인딩 기준으로 GL_CULL_FACE 이므로, 모든 정점은 반시계방향으로 연결되어야 정육면체가 출력될 것이고 그렇게 프로그래밍 되어 있다. 만약 CCW 대신 CW를 사용하면 면의 앞과 뒤가 바뀌어서 육면체의 내부가 출력되게 된다.
GL_CCW
GL_CW
위에서 기술된 모든 함수와 구조체를 알아보는건 시간낭비니까 대표적으로 GL_COLOR_ARRAY만 살펴보기로 하겠다. 추가 정보는 여기
실행 결과는 다음과 같다.
glMatrixMode(GL_PROJECTION); 부터 알아보자, 이 함수는 좌표에 원하는 도형을 모두 그린 후 최종적으로 화면에 출력할 때 적용할 변환 행렬을 설정한다. 이 기능이 있기 때문에 원근감을 느끼도록 멀리있는 물체를 상대적으로 작게 할수도 있고, 원근감을 제거하여 모든 물체를 거리에 상관없이 동일하게 출력할 수 있다. 결국, 최종적으로 우리 눈에 화면이 어떤 방식으로 보이는 지를 행렬로 나타내기 위해 있는 함수이다. 매개변수를 분석하면 이해가 쉽다.
먼저 GL_PROJECTION 이 있는데 이것은 투영 행렬을 사용한다 는 뜻이다. 투영이 뭔지 알아보고 지나가자. 투영이란 어떤 물체가 다른 물체위에 비친 그림자 를 뜻하는 단어이다. 다음 그림을 보자.
벡터b를 벡터a 에 투영시키면 초록색 벡터p가 된다 그래픽스에서 이 투영이 무슨 의미가 있냐면 벡터b를 사람 벡터a를 지면 그리고 a에서 보라색벡터의 방향으로 태양이 있다고 했을때 b의 a에 비친 그림자는 벡터p가 된다. 그리고 벡터b를 벡터p로 변환하는 행렬을 투영행렬 이라고 한다. 이 원리를 확장하여 투영행렬을 잘 설정하면 다음과 같은 효과를 낼 수 있는 것이다.
glLoadIdentity() 는 투영행렬을 Identity 행렬로 바꾼다는 의미이다. Identity 행렬은 단위 행렬이다. 투영 행렬을 초기화해준다는 의미로 받아들일 수 있다.
이제 glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 를 한층 더 이해할 수 있다 OrthoGraphic은 직교투영 이라는 뜻으로, 물체를 정면에서 바라보는 효과를 낸다. 글로는 이해하기 힘드니 그림으로 알아보자.

여기서 실제로 출력되는 뷰 영역은 (left,botton) ~ (right,top) 으로 이 영역만 보이고 다른영역은 보이지 않게된다. 이를 클리빙영역 이라고하며, 우리는 클리빙영역만 볼 수 있으니까 정확히 물체를 정면에서 쳐다보는 효과를 갖게된다. 따라서 우리가 출력하고자 하는 물체의 뒷면은 전혀 보이지 않게된다. 위의 그림 Front Orto 인 경우를 보면 어떤 느낌인지 감이 온다.

또 다른 투영행렬함수인 glFrustum는 glOrtho와 무엇이 다를까. 이 함수는 원근투영행렬을 설정하는 함수로, glOrtho와는 다르게 보이는 물체가 원근감을 갖게 만든다. 마찬가지로 Front Persp 를 보면 이해가 좀더 직관적이다.
여기서는 이만큼만 알아보기로 하고, 다른 글에서 좀더 glMatrixMode에 대해서 체계적으로 정리 하도록 하겠다.
MyVertices 는 정육면체의 정점의 배열로 이뤄져있다. 각 원소는 당연히 정점의 (x,y,z) 성분이다. MyColors 는 정육면체 Color를 설정할 RGB 성분의 배열이고 MyVertexList는 정점의 번호-MyVertices의 인덱스 순서가 정점의 번호이다-를 나열했는데, 이는 이 정점들을 순서데로 그려서 면을 나타낼 것이기 때문이다. 본문을 보도록 하겠다.
glFrontFace(mode) 함수는 와인딩을 설정하는 함수이다. 와인딩이란 정점이 연결되는 방향을 의미하는데 이 함수의 인자로는 GL_CCW GL_CW 두가지가 있다. 그림으로 살펴보자.
*ccw : count clock wise
*cw : clock wisw
어느방향으로 가든 똑같은 삼각형이다그렇다면 이 정점을 잇는 순서가 무슨 의미가 있을까? GL에서는 이 순서로 면의 앞과 뒤를 결정한다. GL에서는 디폴트로 반시계 방향으로 돌았을때 앞면으로 간주된다. 인자로 GL_CW 를 전달한다면 시계방향을 정면으로 설정한다.
그렇다면 다시 면의 앞과 뒤를 설정하는 것이 무슨 의미가 있을까?
culling 이란 그래픽최적화를 위해 사용자가 화면에서 보는 면 말고 안보이는 뒷면을 출력하지 않는 것으로 부하를 줄이는 것을 의미한다.
햄버거를 위에서 본다고 상상해보자 대부분 빵밖에 안보이겠지만 실제로는 참깨빵 위에 순쇠고기 패티두장 특별한 소스 양상추 치즈 피클 양파까지 있다 그런데 고기와 양배추를 전부 출력하는 것은 의미가 없기 때문에 이를 출력하지 않으므로, 그래픽 부하를 줄일 수 있다. 이것으 컬링 이라 하며, glEnable(GL_CULL_FACE) 는 후면제거 컬링 모드를 활성화 한다는 의미이다.
따라서 위 프로그램은 CCW 와인딩 기준으로 GL_CULL_FACE 이므로, 모든 정점은 반시계방향으로 연결되어야 정육면체가 출력될 것이고 그렇게 프로그래밍 되어 있다. 만약 CCW 대신 CW를 사용하면 면의 앞과 뒤가 바뀌어서 육면체의 내부가 출력되게 된다.
다음으로
void WINAPI glEnableClientState( GLenum array
);
void WINAPI glDisableClientState(
GLenum array
);
위 함수는 그래픽 데이터 관리의 효율을 위한 구조체Array 의 사용 여부를 결정하는 역할을 한다. 매개변수와 사용되는 구조체Array는 아래와 같다. 해당 parameter가 enable 함수의 인자로 호출될 경우 사용 가능하다.Parameters
| Value | Meaning |
|---|---|
|
아래도 모두 같은 의미이다.
|
|
See also glEdgeFlagPointer.
|
|
See also glIndexPointer.
|
|
See also glNormalPointer.
|
|
If enabled, use texture coordinate arrays with calls to glArrayElement, glDrawElements, or glDrawArrays.
See also glTexCoordPointer.
|
|
See also glVertexPointer.
|
- size
- color 를 구성하는 컴포넌트의 수이다. 3이나 4가 와야한다 RGB나 RGB
- type
- 컴포넌트의 데이터 타입을 다음 중 하나로 설정한다. GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT, or GL_DOUBLE.
- stride
- The byte offset between consecutive colors. When stride is zero, the colors are tightly packed in the array.
- pointer
- Color 배열 구성을 시작할 첫번째 Color 의 첫번째 컴포넌트의 포인터를 넘겨주어야 한다.
