Software Development/Graphics

OpenGL IBO를 사용한 직사각형 그리기

huiyu 2018. 7. 22. 09:50

이전 VBO를 이용한 큐브 그리기 포스팅을 통해,
화면에 그리는 오브젝트는 vertex (정점)의 집합을 통해 이루어져 있어 Vertex Buffer를 이용하여 그릴 수 있었다.

버텍스 버퍼만을 사용하여 그리는 오브젝트를 다시 살펴보면,
아래와 같이 하나의 사각형은 두개의 삼각형이 필요하고 그에 따라 6개의 정점이 필요했다.


6개의 직사각형이 필요한 큐브 샘플은 6x6, 36개의 정점 배열이 필요했다.
여기에 색상, 노멀벡터 등이 추가 된다면 메모리 사용량은 계속 커지게 된다.
(버텍스를 많이 사용하는 복잡한 오브젝트일 수록 메모리량은 증가)
여기서 버텍스 버퍼만을 이용했을 때 단점을 알 수 있다.


위의 그림과 같이 오브젝트를 그릴 때 공유하는(겹치는) 정점이 있게 된다.
이 때 IBO(Index Buffer Object)를 사용하면 이 문제를 해결할 수 있다.


먼저, 단순한 VBO만을 사용하여 직사각형을 그리는 예제부터 살펴보면,


총 6개의 정점 정보가 필요했다.
위 그림과 같이 두개의 정점정보가 겹친다(o.5, 0.5, 0.5), (-0.5, 0.5, 0.5)

1
2
3
4
5
6
7
8
9
10
11
static const float cube_vertices[] = {
        /* front surface is blue */
         //first triangle
         0.50.50.5,
        -0.5-0.50.5,
         0.5-0.50.5,
         //second triangle
         0.50.50.5,
        -0.50.50.5,
        -0.5-0.50.5
};
cs


IBO를 사용한다면 반복되는 버텍스를 매번 정의할 필요 없이, 한번만 정의하면 된다.
아래와 같이, 사각형의 좌측 하단부터 반시계방향으로 그리며 겹치는 부분은 하나로 정의한다.

1
2
3
4
5
6
7
8
static const float cube_vertices[] = {
        /* front surface*/
        -0.5,-0.50.5,
         0.5,-0.50.5,
         0.50.50.5,
        -0.50.50.5
};
 
cs


아래 그림과 같이 정점의 정의한 순서대로 차례대로 0~3의 인덱스를 갖게 된다.


이 인덱스를 통해 버텍스 정점을 이용해 그렸던대로 index 배열을 정의해주면 된다.

1
2
3
4
5
static const unsigned int cube_elements[] = {
     0,1,2,
     0,2,3
};
 
cs


이제 이렇게 정의한 Index buffer array를 gl과 연결해주고 draw해주면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static const unsigned int cube_elements[] = {
     0,1,2,
     0,2,3
};
 
unsigned int ibo;
 
void generateAndBindBuffer(appdata_s* ad)
{
 //...
  glGenBuffers(1&ad->ibo);
  //Index buffer
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (ad->ibo));
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements), cube_elements, GL_STATIC_DRAW);
 //...
}
 
 
cs

이전 VBO에 해줬던 것과 같이,
glGenBuffers()를 이용해 버퍼를 생성하고, glBIndBuffer()를 통해 버퍼 바인딩, glBufferData()를 이용해 데이터 입력의 순으로 진행한다.

*glBindBuffer, glBufferData호출 시 넘겨주는 인자는 GL_ELEMENT_ARRAY_BUFFER로 넘겨준다.


그리고 draw call 함수를 아래로 변경한다. 
IBO를 이용한 Draw call

1
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
cs

 - mode : 그리는 방법 지정, GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLES, ....
 - count : element의 갯수
 - type : index값의 유형(여기선 unsigned int)
 - indices : index가 저장된 위치 포인터


*index buffer에 대해 glVertexAttribPointer를 호출하지 않는 이유
  -> https://stackoverflow.com/questions/24921350/why-no-glvertexattribpointer-for-index-buffer-object
  -> https://www.opengl.org/discussion_boards/showthread.php/184533-Why-no-glVertexAttribPointer-for-index-buffer-object


실행시키면 아래와 같이 결과를 얻을 수 있다.


소스코드 다운 :

https://github.com/huiyueun/GraphicsStudy/tree/master/4_sdl_rect_indexed



참고)

1. Learn OpenGL ES-An Introduction to index Buffer Objects(IBOs)
2. Wiki books-Modern OpenGL Tutorial 05:Elements-Index Buffer Objects(IBO)
3. Drawing cube with indices

728x90