일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 패턴인식
- 삼성
- NarwalFreo
- Friendship
- Neural Network
- 멤버십
- 신경회로망
- 물걸레자동세척로봇청소기
- 가상화
- 갤럭시탭S8울트라
- 하이퍼바이저
- 동아리
- 물걸레로봇청소기추천
- 고려대학교
- SSM
- Python
- Bidirectional Associative Memory
- 파이썬
- 신경망
- 증강현실
- hopfield network
- 삼성소프트웨어멤버십
- 패턴 인식
- 빅데이터
- 구글 앱 엔진
- Google App Engine
- 인공지능
- BAM
- 삼성전자 소프트웨어멤버십 SSM
- 나르왈프레오
- Today
- Total
정보공간_1
[4기 신촌 김시재] OpenGL에서 텍스처를 빠르게 갱신하는 방법 본문
안녕하세요, 이번에는 OpenGL에서 텍스처를 보다 빠르게 로딩할 수 있는 방법을 알아보려고 합니다. 바로 PBO(Pixel Buffer Object)라고 비디오 메모리를 사용하는 방법이죠. 최근에 동영상을 낱장의 이미지로 받아 OpenGL로 그려보다가 성능이 만족스럽지 않아서 알아본 방법인데 자세히 알아보지 못해 직접 사용은 못해봤지만 그 성능이 인상적인 것 같아서 남겨봅니다.
1. PBO (Pixel Buffer Object)
기본적으로 OpenGL에서 우리가 원하는 이미지 데이터를 텍스처 오브젝트에 복사하는데 glTexImage2D 이나 glTexSubImage2D 를 사용하게 됩니다. 일반적인 경우는 이미지 데이터를 RAM에 올리고 비디오 메모리로 전달해서 그래픽카드가 쓰도록 하는 과정 전체에 걸쳐 CPU를 거치게 됩니다.
Pixel Buffer Object를 사용하는 방식의 경우는 우리가 메모리에 올려놓은 이미지 데이터를 텍스처 오브젝트로 복사할 때 CPU가 아닌 GPU에서 메모리 간 이동에 DMA(Direct Memory Access) 를 수행하도록 하여 빠르게 복사를 수행할 뿐만 아니라 glTexImage2D 와 같은 함수들이 바로 리턴하게 되어 CPU가 다른 작업을 처리하게 해줍니다.
또한 비디오 메모리를 사용하기 때문에 일반 메모리에 비해서 속도가 월등히 빠르고 GPU 입장에서 접근하기도 수월하다는 장점이 있어서 텍스처를 고속으로 로딩하는 것 뿐 아니라 버텍스와 같은 지오메트리 데이터에도 사용됩니다.
2. PBO를 사용하여 텍스처를 빠르게 바꿔보기
OpenGL에서는 비디오 메모리를 가상 메모리에 매핑시키는 방식을 통해 PBO에 접근하여 원하는 작업을 수행할 수 있도록 합니다. 그냥 메모리 어딘가에 접근하는 것 처럼 읽고 쓸 수 있는것이죠. 그럼 이것을 어떻게 사용하는지 알아보도록 하겠습니다.
- PBO 사용 준비
PBO를 사용하기 위한 버퍼 오브젝트 API들은 먼저 확장 기능으로 사용되었다가 OpenGL 1.5 버전이 발표되면서 표준 기능으로 승격되었다고 합니다. 확장 기능에는 ARB라는 접미사가 붙지만 표준으로 승격되면서 ARB하는 접미사를 붙이지 않아도 됩니다.
이 API들은 바로 사용할 수 없고 API 진입점을 먼저 얻은 뒤 사용해야 합니다. glext.h에 보시면 관련 API에 대한 함수 포인터 형태의 자료형이 정의되어 있는데, 이것을 이용해서 진입점을 저장한 뒤 함수처럼 사용하면 됩니다. 물론 확장 기능을 사용하기 위해서는 해당 확장 기능이 지원되는지의 여부를 확인해야 하지만 이 글에서는 단지 갱신이 빠르다는 것을 확인하기 위해 생략하도록 합니다. 대신 글 아래에 매우 좋은 참고 사이트를 소개해 드릴게요 :D
먼저 텍스처를 갱신할 것이기 때문에 glGenTextures, glTexImage2D로 텍스처 오브젝트를 하나 준비해 주세요. 그리고 아래와 같이 진입점으로 사용할 함수 주소를 얻어서 API를 사용할 준비를 마칩니다.
- PBO 생성
이제 PBO를 생성하도록 합니다. 먼저 텍스처의 경우와 같이 ID를 생성하고 버퍼의 크기와 성질을 다음과 같이 정해주도록 합니다.
glBindBufferARB 에서 GL_PIXEL_UNPACK_BUFFER_ARB를 넘겨주고 있는데, 이것은 버퍼 오브젝트가 픽셀 뿐 아니라 버택스 배열 등의 여러 경우도 가능하기 때문에 이를 픽셀 버퍼에 선택한다고 생각하시면 되겠습니다.
glBufferDataARB 는 지정된 크기만큼 버퍼가 저장될 공간을 할당하도록 합니다. 마지막에 넘기는 값은 드라이버가 이 데이터를 어디에 저장할 지 정할 때 참고하는 값으로 용도에 따라 그것에 특화된 위치에 공간을 할당하기 위해 사용되며 각 의미는 다음과 같습니다.
GL_DYNAMIC_DRAW - 자주 변경되는 데이터로 업데이트하기 어려운 장소를 피해서 데이터를 저장하도록 한다GL_STATIC_DRAW - 자주 변경되지 않는 데이터로 읽기에 최적화된 장소에 데이터를 보관하도록 한다GL_STREAM_DRAW - 한번 쓰고 버릴 정도로 자주 바뀌는 데이터에 사용되며 업데이트에 최적화된 장소에 데이터를 저장하도록 한다
이렇게 PBO의 준비가 끝나면 0번 아이디를 지정하여 glBindBufferARB 를 호출해서 PBO 기능을 꺼두셔야 합니다.
- PBO 사용
이제 이렇게 만들어진 PBO에 이미지 데이터를 집어넣고 출력하도록 해보곘습니다. 일단 앞서 말씀드린 것과 같이 이미지 데이터를 PBO에 쓰기위해 메모리 매핑을 수행해야 합니다. 그러기 위한 함수가 glMapBufferARB인데요, 다음과 같이 glMapBufferARB를 통해 포인터를 얻고 일반 버퍼인 것 처럼 사용하시면 됩니다.
여기서 주의할 점이 하나 있다면 glMapBufferARB를 호출하여 포인터를 얻기 전에 glBufferDataARB의 세번째 인자에 NULL을 지정하고 호출해야 한다는 점입니다.
만약 GPU가 버퍼 개체를 사용하는 렌더링 작업을 하고 있으면 glMapBufferARB는 그 작업이 끝날 때 까지 기다리게 됩니다. 그래서 NULL 포인터로 glBufferDataARB를 호출하면 이전의 버퍼 개체가 더 이상 필요하지 않음을 알려주는 셈이 되어 glMapBufferARB가 새로운 데이터 저장소의 위치를 잡아 즉시 리턴할 수 있기 때문이죠.
이렇게 원하시는 이미지 데이터를 옮겼다면 glUnmapBufferARB를 사용하여 매핑을 종료합니다. 이 함수는 GL_FALSE 값을 리턴하기도 하는데, 이 때는 매핑 이후 메모리를 조작하는 사이에 그래픽 카드의 모드 변경이나 전력 조절 등의 문제로 PBO에 어떤 문제가 발생한 것을 뜻하며 다시 데이터를 전송하라는 의미입니다.
이제 이것을 텍스처 오브젝트로 복사해 보겠습니다. 이 과정은 매우 간단합니다. 다음과 같이 텍스처 오브젝트와 PBO를 Bind하고 glTexSubImage2D를 호출하면 됩니다.
그리고 이 텍스처 오브젝트를 선택하고 glTexCoord와 같은 함수를 통해 원하시는 처리를 하시면 되겠습니다.
- PBO 제거
이제 모든 사용이 끝나면 PBO를 제거해야 하는데 이것도 매우 간단합니다. 다음과 같이 생성했던 ID들을 제거하시면 됩니다.
3. 간단한 성능 비교
진짜 얼마나 빠른지 한번 알아보고 싶어서 매우 간단한 프로그램을 작성해 보았습니다. 스페이스를 누르면 PBO를 사용하는지 여부를 선택할 수 있고 약 1초마다 몇 번 프레임이 갱신 되었는지 횟수가 콘솔에 출력됩니다. 그리고 매 프레임마다 이미지 데이터를 새롭게 생성해서 텍스처 오브젝트에 등록되도록 하였습니다.
정밀한 테스트를 수행하지 않더라도 그냥 텍스처 갱신을 수행했을 때(Normal : 약500)보다 PBO를 사용했을 때(PBO : 약 940)가 훨씬 빨리 갱신된다는 것을 알 수 있습니다. 동영상 처럼 계속 텍스처를 갱신시켜야 하는 경우에 사용하면 성능 향상이 있겠죠...?
PBO 지원 여부에 대한 예외처리도 되어있지 않고 테스트 수행 방법도 정밀하지 않기 때문에 보다 자세한 정보와 예제를 확인하고 싶으시면 아래 링크를 추천드립니다. 예제 프로그램이 도움이 많이 될 것입니다.
http://www.songho.ca/opengl/gl_pbo.html
'IT 놀이터 > Elite Member Tech & Talk' 카테고리의 다른 글
[5기 부산 정우진] 람다표현식(Lambda Expressions)과 클로저(Closure) (0) | 2014.04.24 |
---|---|
[4기 신촌 박영웅] App? Accessory? Appcessory! (2) | 2014.01.14 |
[4기 대구 하호성] search.h에 있는 정렬함수 만들기 (0) | 2013.12.05 |
[4기 대구 하호성] nullptr (0) | 2013.12.05 |
[4기 대구 하호성] Unity 3D 안드로이드 플러그인 (1) | 2013.12.05 |