대메뉴 바로가기 본문 바로가기

데이터 기술 자료

데이터 기술 자료 상세보기
제목 라즈베리 파이2를 이용한 OpenGL ES 프로그래밍
등록일 조회수 8907
첨부파일  

오픈 하드웨어의 그래픽 탐구

라즈베리 파이2를 이용한 OpenGL ES 프로그래밍



2015년 2월 출시된 오픈 하드웨어 ‘라즈베리 파이2’는 OpenGL과 EGL(Embedded-System Graphics Library)을 이용해 3D 그래픽을 처리할 수 있다. 이를 활용하면 라즈베리 파이의 쓰임을 더 다양한 영역으로 넓힐 수 있다. 3회에 걸친 연재에서는 라즈베리 파이의 OpenGL과 EGL 환경 그리고 OpenGL ES 1.x와 OpenGL ES 2.0의 프로그래밍 방법에 대해 살펴본다.



라즈베리 파이의 새로운 진화 : 라즈베리 파이 2

● 사물인터넷과 라즈베리 파이
2007년 애플 아이폰의 등장으로 말미암아 ‘스마트’ 시대가 개화했다. 스마트폰, 스마트패드, 스마트TV까지 모든 기술과 기기, 서비스로 ‘스마트’가 유행처럼 번졌다. 이제는 스마트워치가 화두다. 2012년 패블(Pebble)과 소니 라이브뷰로 시작된 스마트워치는 구글의 안드로이드 웨어, 애플워치로 이어지면서 올해 웨어러블 전쟁을 예고하고 있다. 이제 ‘스마트’는 기기를 넘어 가정으로까지 침범하고 있다. 사물인터넷(IoT) 시대가 도래한 것이다. IoT는 2000년대에 유행했던 유비쿼터스(Ubiquitous)의 개념에 뿌리를 두고 있다. 유비쿼터스는 1988년 미국 제록스 연구소의 마크 와이저에 의해 주창된 개념인데, 어디서나 컴퓨터와 네트워크를 사용할 수 있는 환경을 의미한다.

최근 오픈소스 아두이노, 라즈베리 파이와 같은 오픈 하드웨어들이 각광을 받고 있다. 라즈베리 파이는 영국의 라즈베리 파이 재단(Raspberry Pi Foundation)에서 2012년 1월 29일에 출시한 싱글 보드 컴퓨터로, 기초 컴퓨터 과학 교육 증진을 목적으로 고안됐다. 라즈베리 파이는 USB(Universal Serial Bus), 하드웨어 연결을 위한 GPIO, 인터넷 연결을 위한 이더넷(B와 B+ 모델), 사운드 출력 단자, 모니터 연결을 위한 HDMI(High-Definition Multimedia Interface) 등의 다양한 포트들을 제공한다. 데스크톱PC와 동일하게 키보드, 마우스 등의 주변기기를 연결 가능해 소형PC로서 개발은 물론 동영상 재생을 위한 HTPC로도 활용 가능하다.



● 라즈베리 파이와 라즈베리 파이2
라즈베리 파이가 등장한지 3년여의 시간이 지난 2015년 2월 2일 라즈베리 파이2가 모습을 드러냈다. 브로드컴의 BCM2835 (700MHz 싱글코어)에서 BCM2836(900MHz 쿼드코어)로 메인 프로세서가 업그레이드되고, 메모리도 512MB에서 1GB로 늘어났다. 라즈베리 파이2의 성능은 이전 세대보다 6배 이상 향상된 것으로 알려져 있다.

BCM2835는 다양한 포트와 그래픽 처리를 위한 GPU를 통합한 SoC로, ARM11 마이크로아키텍처에 기반을 두고 있지만 ARMv6 코어를 사용해 성능이 다소 낮았다. 반면 라즈베리 파이2의 BCM 2836은 BCM2835와의 호환되면서도 4개의 ARMv7 코어로 구성돼 이전 제품들과 비교되지 않을 만큼 성능이 향상됐다. 그 덕분에 리눅스 배포판인 우분투(Ubuntu)는 물론 MS와의 협력을 통해 윈도우10까지 구동할 수 있다. 참고로 윈도우10은 지원 발표만이 나온 상황이다.





라즈베리 파이의 비디오코어(VideoCore) API

● 라즈베리 파이의 멀티미디어 환경
라즈베리 파이는 리눅스로 구동된다. 파이썬, C/C++ 언어로 시스템 프로그래밍이 가능하며, 유닉스의 표준 GUI 환경인 X 윈도우뿐 아니라 프레임버퍼를 통한 그래픽 출력도 가능하다. 라즈베리 파이의 BCM2835, BCM2836의 GPU는 OpenGL ES 1.1, OpenGL ES 2.0, OpenVG 1.1, Open EGL, OpenMAX 등의 멀티미디어 환경을 지원한다.



라즈베리 파이는 다양한 멀티미디어 환경을 지원하기 위해 별도의 헤더파일(/opt/vc/include)과 라이브러리(/opt/vc/lib)를 제공한다. 이밖에도 /opt/vc/src 디렉터리에는 OpenGL ES를 위한 hello_triangle, H.264 비디오를 출력하는 hello_video, PCM 오디오 출력을 위한 hello_audio, OpenMAX API와 GPU를 사용하는 H.264 인코더를 위한 hello_encode 등의 다양한 예제도 함께 제공한다.

이들은 기본적으로 라즈비안(Raspbian)에 설치돼 있지만, 배포판에 따라 있을 수도 없을 수도 있다. 만약 별도로 설치해야 한다면 깃허브(https://github.com/raspberrypi/firmware)를 이용해 설치하면 된다. 이 라이브러리를 통해 라즈베리 파이에서 OpenGL ES와 EGL을 이용할 수 있다. X 윈도우 대신 프레임버퍼를 이용해 출력하므로 메모리 낭비가 적고 속도도 빠르다.

● 라즈베리 파이의 GPU 초기화
라즈베리 파이의 GPU를 이용하기 위해서는 bcm_host_init( ) 함수로 먼저 GPU를 초기화하고, 그래픽 출력 후 bcm_host_deinit( ) 함수로 할당된 자원을 반환해야 한다. 라즈베리 파이의 그래픽 구조를 살펴보면 VideoCore 위에 리눅스 커널 드라이브로 VCHIQ가 위치하고 있다. GPU가 초기화되면 vc_*_init(vc_vchi_dispmanx_init, vc_vchi_tv_init, vc_vchi_cec_init 또는 vc_vchi_gencmd_init 등) 함수를 이용해 이와 관련된 처리를 할 수 있다.



<리스트 1> hello_screen.c #include < stdio.h> #include < unistd.h> #include < bcm_host.h> /* BCM GPU 사용을 위한 헤더파일 */ int main(int argc, const char **argv) { bcm_host_init(); /* BCM GPU를 위한 초기화 수행 */ getchar(); bcm_host_deinit() /* BCM GPU를 위한 정리 작업 수행 */ return 0; }



<리스트 1>을 빌드하기 위해서는 헤더파일과 라이브러리를 별도로 링크해야 한다. gcc 명령어로 컴파일할 때에는 다음과 같이 ‘-I’에는 헤더파일이 위치한 위치를, ‘-L’에는 라이브러리 위치한 디렉터리를, ‘-l(소문자 L)’에는 링크할 때 사용할 사용할 라이브러리를 각각 지정해야 한다.

pi@raspberrypi ~ $ gcc -o hello_screen hello_screen.c -I/opt/vc/include/ -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux -L/opt/vc/lib/ -lbcm_host <리스트 1>은 GPU의 초기화 코드이므로 이를 빌드하더라도 디스플레이에 어떤 것도 표시되지 않는다. GPU를 초기화했다면 이제는 EGL을 이용해 화면에 OpenGL ES를 출력하기 위한 기본적인 작업들을 처리할 차?와 EGL

● EGL
EGL은 크로노스(Khronos) 그룹에서 관리하는 OpenGL, OpenGL ES, OpenVG와 같은 그래픽 라이브러리의 렌더링(Rendering)을 위해서 사용되는 라이브러리다. 렌더링(Rendering)은 컴퓨터 프로그램을 사용해 모델(또는 이들을 모아놓은 장면인 씬(scene) 파일)로부터 영상을 만들어내는 과정이다(<그림 3> 참조).



OpenGL과 OpenGL ES는 기본적으로 3D를 위한 모델링 언어고, OpenVG는 2D 벡터 그래픽을 위한 모델링 언어다. 모델링 언어는 객체를 표현하는 방법은 제공하지만 화면이나 프린터를 이용한 매체에 출력하는 방법은 제공하지 않는다. 그러므로 모델링 언어로 렌더링하기 위해 안드로이드와 같은 임베디드 기기에서는 EGL을, 데스크톱에서는 GLUT, WGL, Qt 등과 같은 라이브러리가 많이 사용되고 있다.



EGL은 네이티브 플랫폼 인터페이스(Native Platform Inter face)로, 그래픽을 출력하는 플랫폼과 OpenGL ES API사이의 인터페이스를 위한 레이어를 제공한다. 윈도우 시스템과의 인터페이스뿐 아니라 디스플레이 연결을 위한 기능도 제공한다. 리눅스에서 화면에 무언가를 출력할 때 기본적으로는 CPU를 사용한다. 이러한 데이터를 래스터 이미지(Raster Image)라고 하는데, 각각의 픽셀이 RGB 값으로 돼 있다. 비디오 카드의 프레임버퍼(Framebuffer)에 이 래스터 이미지를 밀어넣으면 스크린으로 출력된다. CPU는 화면과 같은 2차원의 벡터 연산에 최적화 돼 있지 않아 전체 래스터 이미지를 다시 생성하기 때문이다. 그러므로 GPU의 OpenGL 가속 기능을 이용해 화면을 출력하면 CPU보다 더 빠르게 처리할 수 있다. 그래픽 출력 시 OpenGL ES와 EGL을 이용할 수도 있다. EGL은 OpenGL ES의 렌더링 이외에도 다양한 기능들을 제공한다. 전원 관리는 물론 프로세스에 의한 다중 렌더링 컨텍스트, 프로세스에서 렌더링 컨텍스트에 대한 객체의 공유, EGL이나 OpenGL ES의 확장 기능 등을 지원하기 위한 추가적인 매커니즘까지 제공한다.

EGL 1.0은 2003년 7월에 발표됐다. 현재 최신 버전은 2014년 8월에 릴리즈된 EGL 1.5다. 라즈베리 파이는 EGL 1.4 버전을 지원하는데, EGL의 각 버전별 스펙은 크로노스 웹사이트(https://www.khronos.org/registry/egl)에서 확인할 수 있다.

● EGL 사용
EGL을 사용하려면 먼저 다음과 같은 초기화 과정을 수행해야 한다.

① 디바이스에 사용가능한 EGLDisplay 디스플레이 객체를 검색하고 초기화를 수행한다.
② EGLConfig 객체를 가져오고 렌더링 출력을 위한 설정을 수행한다.
③ EGL 렌더링을 위한 컨텍스트(EGLContext) 생성하고 관련 설정을 수행한다.
④ EGL에서 OpenGL ES의 모델을 렌더링을 하기 위한 EGLSurface 객체를 생성한다.

지금부터는 <리스트 1>에 EGL을 사용하기 위한 초기화 코드를 추가해 본다.



<리스트 2> hello_egl.c #include < stdio.h> #include < unistd.h> #include < bcm_host.h> /* BCM GPU 사용을 위한 헤더파일 */ #include < EGL/egl.h> /* EGL을 위한 헤더파일 */ #include < EGL/eglext.h> #include < GLES/gl.h> /* OpenGL ES를 위한 헤더파일 */



EGL을 쓰려면 제일 먼저 egl.h와 eglext.h 헤더파일이, OpenGL ES를 위해서는 OpenGL과 같이 gl.h 헤더파일을 추가해야 한다. 헤더파일을 포함시켰다면 이제 main() 함수에서 EGL과 OpenGL을 사용하기 위한 기본적인 초기화 과정을 수행해야 한다.



<리스트 3> <리스트 2>의 hello_elg.c 다음 코드 int main(int argc, const char **argv) { /* 화면의 크기을 저장하기 위한 변수 */ uint32_t screenWidth, screenHeight; /* EGL을 위한 변수 선언 */ EGLDisplay gDisplay; EGLSurface gSurface; EGLContext gContext; EGLConfig gConfig; EGLBoolean result; EGLint numConfig; int32_t success = 0; /* 라즈베리 파이에서 GPU 출력을 위한 자료형 */ static EGL_DISPMANX_WINDOW_T nativeWindow; DISPMANX_ELEMENT_HANDLE_T dispmanElement; DISPMANX_DISPLAY_HANDLE_T dispmanDisplay; DISPMANX_UPDATE_HANDLE_T dispmanUpdate; VC_RECT_T dst_rect, src_rect; /* eglChooseConfig( ) 함수에서 사용할 설정값 */ static const EGLint attribute_list[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 16, /* 색상 깊이 버퍼링을 위해서 필요하다. */ EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; /* eglCreateContext( ) 함수에서 사용할 설정값 */ static const EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 1, /* OpenGL ES 1.x는 1, OpenGL ES 2는 2 */ EGL_NONE };



다음으로 할 일은 다양한 데이터을 초기화하는 일이다. <리스트 1>의 EGLDisplay는 OpenGL을 이용해 렌더링할 모니터와 같은 실제의 스크린을 의미한다. OpenGL과 EGL로 스크린에 그래픽 출력을 하는 데 반드시 필요한 자료형이다. EGLSurface는 EGL을 통해서 생성하는 화면(Surface)을 설정하는 자료형이다. EGL에서는 윈도우(Window), 픽스맵(Pixmap), 픽셀 버퍼(pBuffer) 총 세 가지 종류의 화면이 있다. 이 중 윈도우는 실제 영상을 스크린으로 출력하는 화면으로, 라즈베리 파이에서 그래픽을 출력하는 데 사용된다. 픽셀 버퍼는 스크린에 출력되지 않는 화면인데, 텍스처(Texture)를 위해서 사용된다.

EGL 내에 생성된 화면으로는 온스크린(on-screen) 화면과 오프스크린(off-screen) 화면 이 두 가지가 있다. 오프스크린 화면은 디스플레이되지 않고 랜더링 평면으로 사용할 수 있는 픽셀 버퍼다. 반면 온스크린 화면은 특정 원도우 시스템에 첨부된다. EGLContext는 OpenGL 파이프라인에서 사용하고 있는 상태값을해 현재 사용하고 있는 상태들을 저장하고, 이를 이용해 모델링을 수행한다. OpenGL ES를 사용하기 위해서는 반드시 컨텍스트를 생성한 다음 렌더링을 위한 화면과 매핑시켜야 한다. EGLConfig는 EGL 화면을 설정하는 자료형으로, 렌더링을 수행할 때 필요한 화면 포맷을 설정한다.



<리스트 4> <리스트 3>의 hello_elg.c 다음 코드 bcm_host_init(); /* BCM GPU를 위한 초기화 수행 */ /* EGL 디스플레이(display) 연결을 위한 EGLDisplay 객체 획득 */ gDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); /* EGLDisplay 객체의 초기화 */ result = eglInitialize(gDisplay, NULL, NULL); /* EGL 프레임버퍼 설정을 위해서 필요한 EGLConfig 객체 획득 */ result = eglChooseConfig(gDisplay, attribute_list, &gConfig, 1, &numConfig); /* EGL에 OpenGL ES를 사용하기 위한 설정 */ result = eglBindAPI(EGL_OPENGL_ES_API); /* EGL 렌더링을 위한 컨텍스트(EGLContext) 생성 */ gContext = eglCreateContext(gDisplay, gConfig, EGL_NO_CONTEXT, context_attributes); /* 현재 화면의 크기를 가져온다. */ success = graphics_get_display_size(0 /* LCD */, &screenWidth, &screenHeight); /* 라즈베리 파이에서 출력을 위한 설정 */ dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = screenWidth; dst_rect.height = screenHeight; src_rect.x = 0; src_rect.y = 0; src_rect.width = screenWidth < < 16; src_rect.height = screenHeight < < 16; /* 라즈베리 파이의 출력을 위한 디스플레이 (DISPMANX_DISPLAY_HANDLE_T) 획득 */ dispmanDisplay = vc_dispmanx_display_open(0 /* LCD */); /* 화면 갱신을 위한 DISPMANX_UPDATE_HANDLE_T 자료형을 가져온다. */ dispmanUpdate = vc_dispmanx_update_start(0); /* 라즈베리 파이에서 디스플레이 요소(DISPMANX_ELEMENT_ HANDLE_T)를 추가한다. */ dispmanElement = vc_dispmanx_element_add(dispmanUpdate, dispmanDisplay, 0/*layer*/, &dst_rect, 0/*src*/, &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, (DISPMANX_TRANSFORM_T)0/*transform*/); nativeWindow.element = dispmanElement; nativeWindow.width = screenWidth; nativeWindow.height = screenHeight; vc_dispmanx_update_submit_sync(dispmanUpdate); /* 화면 갱신을 위한 싱크 수행 */ /* EGL 렌더링을 위한 윈도우 화면(EGLSurface) 객체를 생성한다. */ gSurface = eglCreateWindowSurface(gDisplay, gConfig, &nativeWindow, NULL); /* EGL 컨텍스트와 EGL 화면을 서로 연결한다. */ result = eglMakeCurrent(gDisplay, gSurface, gSurface, gContext);



EGL 사용 전 반드시 bcm_host_init() 함수를 통해 라즈베리 파이의 GPU를 초기화 해야 한다. EGL을 사용하려면 반드시 정해진 순서를 따라야 한다. eglGetDisplay() 함수는 출력 스크린에 대한 EGLDisplay 객체를 가져오고, eglInitialize() 함수를 이용해 초기화할 수 있다. EGLDisplay 객체의 생성과 설정이 끝나면 eglChooseConfig() 함수로 현재 프레임버퍼와 관련된 설정에 필요한 EGLConfig를 가져온다. eglChooseConfig() 함수에 현재 사용할 화면의 RGBA 버퍼의 비트수와 색상 깊이(Color Depth), EGL 화면의 타입 등을 배열로 만들어서 설정한다. 다음 eglCreateContext() 함수를 이용해 EGL 렌더링을 위한 컨텍스트(EGLContext) 생성한다. 현재 EGL에서 사용할 OpenGL ES의 버전을 설정하면 된다. 만약 OpenGL ES 1.x를 사용할 경우 1을, OpenGL ES 2.0의 경우 2를 대입한다.

라즈베리 파이에서 그래픽을 사용려면 EGL 이의의 별도 작업이 필요하다. 먼저 vc_dispmanx_display_open() 함수로 라즈베리 파이에서 출력을 위한 기본 디스플레이(DISPMANX_DISPLAY_HANDLE_T 자료형)를 획득한 후 화면 갱신을 위한 DISPMANX_UPDATE_HANDLE_T 자료형을 가져온다. 다음 라즈베리 파이에서 디스플레이를 위한 요소(DISPMANX_ELEMENT_HANDLE_T)를 추가한다. 마지막으로 vc_dispmanx_update_submit_sync() 함수를 이용해 화면을 갱신하고 싱크를 맞춘다.

eglCreateWindowSurface() 함수로 EGL에서 OpenGL ES로 모델링한 데이터를 렌더링하기 위한 EGLSurface 객체를 생성한다. 그 이후 eglMakeCurrent() 함수와 EGLDisplay, EGLSurface, EGLContext, EGLConfig 자료형을 이용해 EGL 컨텍스트와 다른 수행결과가 EGL 화면으로 출력되도록 연결한다.



<리스트 5> <리스트 4>의 hello_elg.c 다음 코드 /* OpenGL에서 glClear( ) 함수로 버퍼를 지울때의 색상을 설정 */ glClearColor(0.15f, 0.25f, 0.35f, 1.0f); /* 색상 버퍼 비트(GL_COLOR_BUFFER_BIT) 지우기 */ glClear(GL_COLOR_BUFFER_BIT); /* 현재 윈도우에 OpenGL의 표시를 위한 영역의 설정 */ glViewport(0, 0, screenWidth, screenHeight); eglSwapBuffers(gDisplay, gSurface); /* OpenGL ES의 내용을 EGL로 출력 */ getchar(); bcm_host_deinit(); /* BCM GPU를 위한 정리 작업 수행 */ return 0; }



EGL의 명령어들이 elg로 시작되듯 OpenGL과 OpenGL ES의 함수들은 gl로 시작된다. glClearColor() 함수에는 glClear() 함수를 통해 버퍼를 지우고 채울 색상을 지정한다. 일반적으로 색상은 빨강(Red), 녹색(Green), 파랑(Blue)의 값들은 0~255의 8비트의 정수 값을 표현하지만 OpenGL은 0.0에서 1.0의 실수값을 사용한다. glClearColor() 함수는 4개의 인자를 받는다. 빨강(Red), 녹색(Green), 파랑(Blue)의 색상과 투명도를 의미하는 알파(Alpha) 값이 그것이다. 이렇게 설정된 색상은 glClear() 함수를 통해 버퍼를 채우는 데 사용된다. <리스트 5>의 glClearColor() 함수에는 ‘0.15f, 0.25f, 0.35f, 1.0f’ 값이 지정돼 있는데, 이는 하늘색 컬러다. 화면에 사용할 영역은 glViewport() 함수로 설정한다. 이 예제에서는 원점에서부터 graphics_get_display_size()로 가져온 윈도우 크기를 지정했다. 프로그램이 종료되면 화면에 출력한 내용이 사라진다. 내용 확인을 위해서 <리스트 5>는 getchar() 함수로 사용자 입력을 기다리고, 키보드 입력이 있으면 프로그램이 종료되도록 구현했다. 지금부터는 <리스트 5>를 실제로 빌드해 보자. 먼저 여기서 사용한 EGL과 OpenGL ES 1.x를 위해 EGL과 GLESv1_CM 라이브러리를 다음과 같이 링크해야 정상적으로 빌드가 수행된다. <리스트 5>를 실행하면 화면 가득히 하늘색이 채워질 것이다. pi@raspberrypi ~ $ gcc -o hello_egl hello_egl.c -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads/ -I/opt/vc/include/interface/vmcs_host/linux -L/opt/vc/lib -lbcm_host -lEGL -lGLESv1_CM

● OpenGL ES 1.x 간단한 프로그래밍 지금부터는 <리스트 2>부터 <리스트 5>까지의 코드를 변경해 화면에 흰색 사각형이 출력해 보자(<리스트 6> 참조). 이를 통해 OpenGL ES 프로그래밍을 조금은 이해하게 될 것이다.

<리스트 6> OpenGL ES를 이용한 흰색 사각형 출력 glClearColor(0.15f, 0.25f, 0.35f, 1.0f); /* OpenGL에서 glClear( ) 함수로 버퍼를 지울때의 색상을 설정 */ glClear(GL_COLOR_BUFFER_BIT); /* 색상 버퍼 비트(GL_COLOR_BUFFER_BIT) 지우기 */ glViewport(0, 0, screenWidth, screenHeight); /* 현재 윈도우에 OpenGL의 표시를 위한 영역의 설정 */ /* 출력될 도형을 위한 좌표 설정 */ GLfloat points[] = { -0.5, -0.5, 0.0, /* 좌측 아래 */ 0.5, -0.5, 0.0, /* 우측 아래 */ 0.0, 0.5, 0.0, /* 중앙 위쪽 */ }; glColor4f(1.0, 1.0, 1.0, 1.0); /* 출력될 도형을 위한 색상 설정 */ glEnableClientState(GL_VERTEX_ARRAY); /* 정점 배열 사용을 설정 */ glVertexPointer(3, GL_FLOAT, 0, points); /* 그래픽 출력을 위한 정점배열 사용에 대한 설정 */ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); /* 삼각형을 그린다. 처리할 정점의 수 : 3개 */ glDisableClientState(GL_VERTEX_ARRAY); /* 그래픽 출력을 하고 나서 정점 배열 사용에 대한 설정 해제 */ eglSwapBuffers(gDisplay, gSurface); /* OpenGL ES의 내용을 EGL로 출력 */ getchar(); bcm_host_deinit(); /* BCM GPU를 위한 정리 작업 수행 */ return 0; }



삼각형을 그리기 위해서는 우선 각 모서리들의 좌표값이 필요하다. OpenGL ES는 3차원을 표시하기 위해 x, y, z에 대한 좌표를 이용한다. 2차원의 경우 간단하게 x, y좌표만 있으면 된다. 이러한 좌표들을 배열로 저장하면 glEnableClientState() 함수와 glVertexPointer() 함수로 간단하게 객체들을 표현할 수 있다. 참고로 OpenGL의 좌표계는 오른손 좌표계로, 기본값이 -1.0에서 1.0의 크기인 직교좌표계(Orthogonal Coordinate System)이다. 일반적인 화면에 쓰이는 좌표계와는 다르게 기본적으로 원점은 중앙에 위치하고 있고, y 축의 값은 아래에서 위로 올라갈수록 값이 증가한다.

<그림 6>에서 z 축은 모두 0.0이므로 x와 y 공간에 표시하면 된다. 그러므로 삼각형의 좌표는 (-0.5, -0.5), (0.5, -0.5), (0.0, 0.5)다. 좌표를 설정했다면 glColor4f() 함수로 채워질 색상을 설정해야 한다. 앞선 예제의 glClearColor()와 같이 0.0에서 1.0 사이의 실수값로 R, G, B, A의 각 요소에 대한 값을 설정할 수 있다. 여기서 0.0은 검은색아고, 1.0은 흰색이다. 삼각형의 각 점은 배열이므로 glEnableClientState()로 OpenGL에 ‘정점을 배열로 사용함’을 설정해야 한다. glVertexPointer() 함수로 정점의 평면 수(x, y, z), 정점에 대한 자료형, 그리고 배열을 설정한다. 실제 삼각형은 glDrawArrays() 함수로 그리게 된다. 그려질 도형의 형태와 정점을 수를 지정해서 말이다. 삼각형 드로잉이 끝나면 glEnableClientState() 함수를 통해 설정한 상태를 gl DisableClientState() 함수로 해제한다. 다음 eglSwapBuffers( ) 함수로 OpenGL ES에서 모델링한 내용을 EGL로 출력한다. 이제 삼각형 코드를 빌드해 보자. 빌드할 때에는 앞선 예제와 옵션을 그대로 이용하면 된다. 그러면 파란 화면에 흰색(1.0, 1.0, 1.0, 1.0)의 삼각형이 나타날 것이다(<그림 7> 참조).

출력된 삼각형은 독자의 디스플레이 패널 비율에 따라 정삼각형으로 보이지 않을 수 있다. 와이드 모니터에서는 16:9 비율에 맞춰 삼각형이 수평으로 더 길게 보일 것이다. 이를 정삼각형으로 표시되도록 하려면 별도의 설정을 추가해야 한다. 이와 관련된 내용은 다음에 살펴보겠다.



출처 : 마이크로소프트웨어 4월호

제공 : 데이터전문가 지식포털 DBguide.net