본문 바로가기
C++ 200제/코딩 IT 정보

[OpenGL ES] 13. 버퍼 오브젝트, Rendering, Pre-Render

by vicddory 2017. 10. 31.

[OpenGL ES] 13. 버퍼 오브젝트, Rendering, Pre-Render


Using the OpenGL ES Buffer Objects

Buffer Object를 쓰는 것은 간단하다. Buffer Object를 다시 bind 하면 된다. OpenGL ES Buffer Object는 2개를 bind 할 수 있다는 것이 기억나는가?


GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER를 동시에 bind 할 수 있다.


bind하고 나선 OpenGL ES glDraw*를 이용하여 buffer object의 시작 index를 알려주면 된다. 배열 데이터 대신에 시작 index를 줘야 하므로, 시작 번호는 void형 pointer가 된다. 시작 index는 반드시 byte여야 한다.


OpenGL ES 버퍼 오브젝트[OpenGL ES] 13. 버퍼 오브젝트, Rendering, Pre-Render


위의 코드(이전 포스트의 마지막 예제 [링크])를 아래처럼 간단히 쓸 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
GLuint arrayBuffer, indicesBuffer;
 
// Generates the name/ids to the buffers
glGenBuffers(1&arrayBuffer);  
glGenBuffers(1&indicesBuffer);
 
// Assume we are using the best practice to store all informations about
// the object into a single array: vertices and texture coordinates.
// So we would have an array of {x,y,z,s,t,  x,y,z,s,t,  ...}
// This will be our "arrayBuffer" variable.
// To the "indicesBuffer" variable we use a
// simple array {1,2,3,  1,3,4,  ...}
 
// ...
// Proceed with the retrieving attributes and uniforms locations.
// ...
 
// ...
// Later, in the render time...
// ...
 
// ...
// Uniforms definitions
// ...
 
glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);  
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer);
 
int fsize = sizeof(float);  
GLsizei str = 5 * fsize;  
void * void0 = (void *0;  
void * void3 = (void *3 * fsize;
 
glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, str, void0);  
glVertexAttribPointer(textureLoc, 2, GL_FLOAT, GL_FALSE, str, void3);
 
glDrawElements(GL_TRIANGLES, 64, GL_UNSIGNED_SHORT, void0); 
cs


만일 oop 언어를 쓴다면, 위의 코드를 좀 더 좋은 구조로 만들 수 있을 것이다.


이게 OpenGL ES shader와 program object에 대한 기본 개념이다. 이제 마지막 부분으로 넘어가자. EGL API 사용 방법을 끝내자.


OpenGL ES Rendering

기기의 화면에 그리는 render의 기본 종류를 보여줄 거다.


이미 알겠지만 texture나 frame buffer처럼 off-screen에 그릴 수도 있고, 이걸 파일로 저장할 수도 있고 이미지로 만들어 화면에 보여줄 수도 있다.


OpenGL ES Pre-Render

나는 2단계로 rendering을 나누는 것이 좋다.


첫 번째, Pre-Render 단계는 이전 render 작업 시의 자취를 지우는 것이다. 중요하다. frame buffer가 뭔지 기억나는가? Render buffer들로부터 나오는 이미지의 집합이다. 그래서 완전한 render를 만들어 어딘가에 보여주고 나서도 render buffer 안의 이미지들은 남아있다.


Pre-render 단계에서 하는 일은 render buffer를 모두 초기화하는 것이다.


만약 당신이 render buffer 안에 있는 이전 이미지들을 재사용하려는 것이 목적이라면 OpenGL ES pre-render 단계가 필요 없다. Frame buffer를 초기화하는 것이 간단하다.


Clearing the Render Buffers


GLvoid glClear(GLbitfield mask)


mask: The mask represent the buffers you want to clean. This parameter can be:

GL_COLOR_BUFFER_BIT: To clean the Color Render Buffer.

GL_DEPTH_BUFFER_BIT: To clean the Depth Render Buffer.

GL_STENCIL_BUFFER_BIT: To clean the Stencil Render Buffer.


잘 알겠지만 모든 명령어는 최근에 bind 된 객체에까지 영향을 미친다.


OpenGL ES Rendering[OpenGL ES] 13. 버퍼 오브젝트, Rendering, Pre-Render


따라서 위의 함수를 호출하기 전에 원하는 OpenGL ES frame buffer에 연결해야 한다.

마스크 파라미터가 bit이기 때문에, OR 비트 연산자 “|” 를 사용할 수 있다. (그렇기에 한 번에 많은 buffer를 지울 수 있다)


1
2
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);  
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
cs


opengl을 초기화하는 다른 함수도 있지만, 위의 함수를 사용하는 게 여러모로 최고다.


pre-render 단계는 glDraw*가 호출되기 전에 실행되어야 한다. 일단 초기화가 됐으면 3차원 객체를 그릴 차례다.


하지만 그리는 것은 내가 아까 말한 2단계 중 하나가 아니다. 이것은 단지 그리기일 뿐이다.


출처 : All About OpenGL ES 2.X 번역

[OpenGL ES] 13. 버퍼 오브젝트, Rendering, Pre-Render

댓글