배치 성능을 향상시키는 방법


9

모바일 플랫폼 용 스프라이트 기반 2D 게임을 개발 중이며 그래픽을 렌더링하기 위해 OpenGL (실제로는 Irrlicht)을 사용하고 있습니다. 먼저 간단한 방법으로 스프라이트 렌더링을 구현했습니다. 모든 게임 오브젝트는 자체 GPU 드로우 콜을 사용하여 쿼드로 렌더링됩니다. 즉, 200 개의 게임 오브젝트가있는 경우 프레임 당 200 개의 드로우 콜을했습니다. 물론 이것은 나쁜 선택이었고 모든 GPU 드로우 콜에 약간의 CPU 오버 헤드가 있기 때문에 내 게임은 완전히 CPU에 바인딩되었습니다. GPU는 대부분 유휴 상태를 유지했습니다.

이제 객체를 큰 배치로 수집하고 몇 번의 그리기 호출로 이러한 배치를 렌더링하여 성능을 향상시킬 수 있다고 생각했습니다. 나는 배치를 구현하여 (같은 질감을 공유하는 모든 게임 객체가 동일한 배치로 렌더링되도록) 내 문제가 사라 졌다고 생각했습니다.

왜? 글쎄, 나는 200 개 이상의 게임 개체를 가지고 있으며 초당 60 번 업데이트됩니다. CPU의 정점에 대한 새로운 위치 (번역 및 회전)를 다시 계산 해야하는 모든 프레임 (모바일 플랫폼의 GPU는 인스턴스화를 지원하지 않으므로 거기에서 할 수 없습니다) 및이 계산을 초당 48000 (200 * 60 * 4 이후) 모든 스프라이트에는 4 개의 정점이 있습니다)) 너무 느리게 보입니다.

성능 향상을 위해 무엇을 할 수 있습니까? 모든 게임 오브젝트는 매 프레임마다 움직이거나 회전하며 (거의) 모든 정점 위치를 다시 계산해야합니다. 내가 생각할 수있는 최적화 만 회전을위한 조회 테이블이므로 회전을 계산할 필요가 없습니다. 스프라이트가 도움이 될까요? 불쾌한 해킹이 있습니까? 다른 거있어?

감사.

답변:


5

안드로이드 에 irrlicht 포트 를 사용 했습니까 ? Android 및 iPhone의 2D 스프라이트의 경우 배치와 같은 트릭을 사용합니다. OpenGL ES 1.x 및 2.x에서 많은 솔루션을 시도합니다.

  • z (평행) 및 텍스처별로 정렬하고 CPU에서 변환을 수행하고 glDrawArrays 또는 glDrawElements (가장 빠른 방법)를 호출하십시오. 가능하면 큰 질감을 사용하십시오.
  • 각 프레임마다 모든 정보를 새로 고치기 때문에 VBO와 동일한 트릭이 더 빠르지는 않습니다. 정적 스프라이트에 유용 할 수 있습니다.
  • OpenGL ES 2.x를 사용하고 정점 셰이더를 사용하여 위치 계산 (느리게)
  • PointSprites 사용 (정사각형이 아니고 너무 많은 투명 픽셀이 필 레이트를 죽이면 해결책이 없음)
  • gldrawtexoes 확장명을 사용하십시오 ...
  • 각 스프라이트마다 드로우 콜 사용 (가장 느린 방법)

따라서 모든 변환은 OGLES 1.x 또는 OGLES 2.x 용 CPU에 의해 수행됩니다. 네온 명령어가 있으면이를 사용하여 계산 속도를 높일 수 있습니다.

추신 : 아이폰이나 안드로이드 장치에서 나는 CPU 제한이 없지만 채우기 속도가 제한적입니다. 따라서 오버 드로를 제한하는 것이 매우 중요합니다.


훌륭합니다. 이것은 내가 찾고있는 것입니다. 나는 당신의 Irrlicht 포트를 알지 못했지만 Irrlicht의 버전이 이미 iOS에서 실행 중입니다. CPU 제한이 없다고 말하십시오-얼마나 많은 스프라이트를 그리십니까? 예를 들어 iPhone에서 100 개의 스프라이트에 대한 프레임 속도는 무엇입니까? 200 개의 객체가 있으면 초당 48000 계산을 수행합니다. 충전 속도에 대한 당신의 요점은 좋습니다.
user4241

정적 스프라이트 (배경)는 VBO에 있습니다. 시차마다 하나의 VBO를 사용합니다. 그렇지 않으면 Moblox에 100에서 200 개의 스프라이트가 있습니다. 3G를 포함한 모든 아이폰에는 30fps 이상이 있습니다. 그러나 큰 스프라이트는 비용이 매우 많이 듭니다 (충전 문제) ....
Ellis

파티클 엔진을 개발 중입니다.이 엔진은 CPU에서 수행되는 모든 위치 계산에서 최대 22,000 개의 입자를 사용할 수 있으며 극단적 설정 (3GS 및 iPhone4)으로 10fps를 갖습니다. 따라서 프레임 속도가 좋은 3GS 또는 iPhone4에서 1000 개의 스프라이트가 가능해야합니다.
Ellis

매우 도움이되었습니다! 파티클 엔진을 어떻게 구현하고 있습니까? 쉐이더를 가지고 놀고 있다고 생각하십니까?
user4241

각 입자 크기를 설정하려면 gl_PointSize가 필요하기 때문에 쉐이더를 사용합니다. 오래된 전화가 내 목표가 아니기 때문에 OGLES 1.x에서 더 이상 작동하지 않습니다. 먼저 모든 코드는 OGLES 1.x, OGLES 1.x 및 OGLES 2.x (성능 개선 없음) 및 OGLES 2.x (렌더링 개선)였습니다.
Ellis

1

VBO를 사용하는 것이 좋습니다. 각 정점에는 렌더링 된 객체의 위치 / 회전이 포함되어 있으며 텍스처를 기반으로 배치가 수행됩니다. 나는 ogl ES에 익숙하지 않으므로 지원하는 glsl 버전이 확실하지 않지만 일련의 텍스처를 기반으로 배치하고 전달할 4 개 이상의 텍스처 중 하나를 저장할 수 있습니다. 정점 내부를 사용하게됩니다. 포인트 스프라이트는 전송하는 데이터의 양을 크게 줄이므로 성능을 향상시킬 수 있으며, 배치를 수행하면 배치를 수행해도 성능이 저하되지 않습니다. 또한 셰이더에서 회전을 계산하고 int / float 값을 매개 변수 또는 정점 자체에만 전달하여 성능을 약간 향상시킬 수 있습니다. (매개 변수가 더 빠를 것입니다.


답변 주셔서 감사합니다. 셰이더에서 회전 계산에 대한 제안은 탁월하지만 불행히도 셰이더를 지원하지 않는 OpenGL ES 1을 사용하고 있으므로 고정 파이프 라인이 붙어 있습니다. 포인트 스프라이트를 시도하지만 크기에 대한 상한이 있으므로 모든 경우에 사용할 수는 없습니다. 나는 여전히 VBO에 대해 약간 비관적입니다. 프레임마다 각 정점의 위치를 ​​다시 계산하는 경우 VBO가 어떻게 도움이됩니까?
user4241

버텍스 데이터가 GPU에 머무를 수있게하여 각 프레임마다 GPU로 전송해야하는 데이터의 양이 줄어 듭니다. 이 기법을 활용하기 위해 셰이더가 필요하지 않습니다. 각 스프라이트의 기본 위치 (원점 등)가있는 경우 버텍스 데이터를 전혀 변경할 필요가 없습니다. draw를 호출하기 전에 변환됩니다. 그러나 배치 할 때이 작업이 어려울 수 있습니다. 고정 기능을 사용하면 VBO로 전환하고 배치를 삭제하는 것이 적어도 더 유리할 것입니다.
sringer

너의 의도를 알 겠어. 결국, 배치에 대해 이야기하는 것이 아니라 단순히 하나의 드로우 콜을 사용하여 하나의 게임 오브젝트를 그립니다. 일괄 처리가없는 VBO가 내 게임에서 FPS에 어떤 영향을 미치는지 확실히 테스트 할 것입니다. 그러나 프레임 당 200 개의 드로우 콜이 너무 큰 소리를냅니다. 그러나 나는 그걸로 살아야한다고 생각합니다. 다른 답변이 표시되지 않으면 답변을 수락하겠습니다.
user4241

1

인스 턴싱이없는 모바일 플랫폼을 언급했습니다. 그러나 여전히 버텍스 쉐이더가 있습니까?

이 경우에도 의사 인스 턴싱을 수행 할 수 있으며 매우 빠릅니다. 모서리 점 (예 : 스프라이트의 중심점 (예 : -1 / -1, 1 / -1, 1/1, -1/1) 및 필요한 텍스처 좌표)을 사용하여 VBO (GL_STATIC_DRAW)를 만듭니다. .
그런 다음 모든 그리기 호출에 대해 일반 정점 속성 중 하나를 스프라이트의 중심점으로 설정하고 버퍼가 바인딩 된 두 개의 삼각형을 그립니다. 정점 셰이더 내에서 일반 정점 속성을 읽고 정점의 좌표를 추가하십시오.

그러면 모든 스프라이트에 대한 데이터 전송을 차단할 수 있으며 훨씬 빠릅니다. 실제 드로우 콜의 수는 그다지 중요하지 않습니다.


OpenGL ES 2.0에 적합한 솔루션입니다. 불행히도 쉐이더가 전혀없는 ES 1을 사용하고 있습니다.
4241

0

각 프레임마다 GPU에 전송하는 데이터 양에 문제가 있습니다. 각 배치에 대해 VBO를 생성하고 한 번 채우고 배치를 그릴 때 해당 변환 행렬 (glMultMatrix 또는 ES 2.0을 사용하는 경우 쉐이더를 통해)을 적용하십시오.


고유 한 변형이있는 200 개의 개별 게임 개체가있을 때 이것이 어떻게 도움이됩니까? glMultMatrix를 사용하면 내가 원하지 않는 모든 객체에 동일한 변환이 적용됩니다. 또한 GPU로 데이터를 보내는 것은 병목 현상이 아닙니다. CPU 측 변환을 제거하면 성능이 매우 좋습니다.
user4241

예. 그러나 VBO가 올바르게 적용되면 여전히 성능을 향상시킬 수 있습니다. 현재 200 개의 오브젝트를 어떻게 렌더링합니까? glBegin / glEnd를 사용하고 있습니까?
TheBuzzSaw

1
사용자 정의 장면 노드와 함께 Irrlicht 3D 엔진을 사용하고 있으므로 OpenGL을 직접 사용하지 않습니다 (그러나이 경우 간단한 glBegin / glEnd를 사용한다고 가정합니다). 매 프레임마다 전체 버퍼를 수정해야하므로 VBO가 실제로 도움이됩니까? 또한 이것은 버텍스 변환 계산으로 인해 CPU 바인딩에 관한 근본적인 문제를 해결하지 못합니다. 그러나 어쨌든 귀하의 답변에 감사드립니다!
user4241
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.