2013-12-08 1 views
0

VBO를 사용하여 16x16x16 큐브를 100 개 렌더링하는 실험용 응용 프로그램을 작성했습니다. VBO 측정 이외에도 12 명이 넘는 사람들이 칭찬 해 왔고, 실제 Minecraft 스타일 게임에서 사용하고있는 청크 당 표시 목록보다 훨씬 성능이 좋다고 나에게 말했습니다.VBO를 사용할 때 필요한 메모리 향상

하나의 큐브/삼각형에 초점을 맞춘 잘 못된 많은 자습서를 내가 필요한 그림 그리기 양을 처리 할 수있는 무언가로 바꾸는 것은 힘든 과정이었습니다. 나는 아직도 VBO가 내 게임보다 디스플레이 목록보다 낫다는 것을 확신하지 못한다.

대부분 인터리브 된 VBO 데이터가 한 번만 (청크가로드 될 때) 빌드 된 다음 각 render 호출에서 버퍼 ID가 바인딩되고 glDrawArrays이 호출되도록 코드를 수정했습니다.

성능을 처리하는 방법을보기 위해이 실험용 앱에서 블록/청크의 양을 천천히 늘려 가고 있습니다. 실제 게임에서는 모든 청크에서 16x16x128 블록을 처리해야하며 최대 20x20 청크가로드됩니다. 그 중 약 60 %가 렌더링 된 견고한 블록이 될 것이므로 800 만 블록이 될 것입니다. 그것은 내가 시작한 디스플레이리스트 메소드를 사용하여 별다른 문제없이 렌더링합니다. 내 버퍼가 꽤 확신

Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory 
at java.nio.Bits.reserveMemory(Bits.java:658) 
at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123) 
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:306) 
at org.lwjgl.BufferUtils.createByteBuffer(BufferUtils.java:60) 
at org.lwjgl.BufferUtils.createFloatBuffer(BufferUtils.java:110) 
at com.helion3.opengl.rendering.TextureQuadRenderer.<init>(TextureQuadRenderer.java:25) 
at com.helion3.opengl.shapes.Chunk.<init>(Chunk.java:13) 
at com.helion3.opengl.shapes.World.<init>(World.java:18) 
at com.helion3.opengl.Game.start(Game.java:90) 
at com.helion3.opengl.Launcher.main(Launcher.java:19) 

:

그러나, 나는 VBO 지금 허용 수준 내에서 렌더링 성능에도 불구하고, 나는 메모리 제한을 타격하지 않고 10 덩어리의 반경을 생성 할 수 없습니다 적절한 수의 설치가 필요합니다. I는 호출

4096 곱한 큐브 당 192 플로트 (3 개 정점, 3 색, 여섯 개면과면 당 4 개 개의 꼭지점을 곱하여 2 텍스처 좌표)를 사용

BufferUtils.createFloatBuffer( - 청크 테스트 블록 수.

실제 게임에서는 공기에 노출되지 않은 블록면을 렌더링하지 않습니다.하지만이 테스트 응용 프로그램에서 블록을 렌더링하더라도 16x16x16 블록 만 렌더링합니다.

어떻게하면 VBO 메모리를 더 잘 관리 할 수 ​​있습니까? 내 VBO 테스트 app rendering code, chunk code

언제 VBO가 모든 사람들을 어떻게 팔아 버렸는가? 롤

P. 나는 이제 인스턴스화에 뛰어 들고 어떻게 도움이되는지 알아 보겠습니다.

+0

VBO를 메모리 효율적인 방식으로 사용하려면 부동 소수점 값으로 색상 저장을 중단하십시오. 'GLubyte'는 저장 공간의 1/4을 사용합니다. 또한 왜 당신이 자바 메모리가 부족한 지 잘 모르겠습니다. VBO는 디스플레이 드라이버 ... VRAM이 관리하는 주소 공간에 모든 용도와 목적으로 메모리를 할당합니다. VBO를 올바로 사용한다면 애플리케이션 자체에서 관리해야하는 Java 메모리를 크게 늘리지 않아야합니다. 즉, GL에 데이터를 보낸 후에 원래의 ByteBuffer를 해제해야합니다. –

+0

데이터를 바인딩 한 후 원본 ByteBuffer를 해제하고 모든 예제가 어떻게 나타나는지에 따라 다음과 같은 색상이 제공됩니다. 모든 것이 인터리브되어 하나의 플로트 버퍼 (청크 당)에 있습니다. – helion3

+0

흠 원래 ByteBuffer를 'clear'- 'null'로 설정하면 메모리 prob를 해결하는 것으로 보이지만 20x20 청크로 성능이 저하됩니다. 지금은 스케일에 있지만, 실제로 큐브 전체가 렌더링되지 않도록 설정해야합니다.곧 내가 원래 게임을 할거야 ... LOL – helion3

답변

3

실제 게임에서 공기에 노출되지 않은 블록면을 렌더링하지 않습니다.하지만이 테스트 응용 프로그램에서 블록을 렌더링하더라도 16x16x16 블록 만 렌더링합니다.

아주 좋습니다. 사람들은 Minecraft 스타일 렌더러를 쓰면서 OpenGL 을 보내려고 할 때 실수를 저지르기 때문에 블록의 모든 부분이 (이면 모두 인 경우 악화됩니다). 대신 실제로 볼 수있는 서페이스를 결정하고 VBO에있는 서페이스 만 유지해야합니다. 공간 세분 구조를 사용하면 여기에서 도움이됩니다. 세계와 같은 Minecraft는 Octree의 냄새를 맡습니다. Octree는 사소한 것으로 실제 물건을 저장할 수 있습니다. (이 내용은 다른 사람들이 Q & A에 해당하는 내용입니다.)


명심해야 할 또 다른 한가지는, 모든 큐브로 렌더링하기 때문에 당신이 (동일) 큐브, 수백만의 주위에 보관하지 않아도 바로 변환됩니다. 인스 턴싱을 사용하는 경우 하나면 충분합니다.

인스 턴싱을 사용하면 인스턴스를 완전히 설명하기 위해 블록 당 4 개의 정수 만 필요합니다 (위치는 3 개, 표면은 1 개, GL_TEXTURE_2D_ARRAY에서로드). 정수는 더 작은 종류 (단점은 오래된 GPU가 효율적으로 처리 할 수 ​​없다는 단점이 있기 때문에)에 적합합니다. 한 큐브가 1m³를 나타냅니다. 그런 다음 16 비트 정수는 (65536m) ³의 세계를 제공합니다. 또한 Minecraft 스타일의 게임에는 256 종류 이상의 표면이 거의 필요 없습니다. 따라서 그것을 표현하기 위해 8 비트 정수를 사용하십시오. 그런 다음 눈에 보이는 표면만을 고려하면 블록이 너무 많아서 VBO에 볼륨이 많이있을 필요가 없습니다.

이것은 실제 메모리 세이버가 될 수 있습니다. 32 비트 부동 소수점에서 16 비트 정수로 이동하면 메모리의 50 %를 절약 할 수 있습니다. 3x32 비트 플로트 색상 대신 재료 색인에 단일 8 비트 정수를 사용하면 해당 메모리 요구량을 1/12로 줄일 수 있습니다.


렌더링 부하를 줄이려면 세계의 모든 큐브가 병렬로 사용될 수 있습니다. 이렇게하면 숨겨진 표면을 처리하는 것보다 현저하게 쉽게 제거 할 수 있습니다. 큐브를 볼 때 8 + 6 가지 주요 방향이 있습니다. 8 개의면이 모서리를 공유하고 3 개의면이 보이고 6 개의 방향이보고있는 표면 직접 볼 수 있습니다. 각 사례가 현재의 관점에서 적용되는 세계의 주요 평면을 결정하는 것은 오히려 쉽습니다. 따라서 큐브 기본 템플릿의 변형을 14 가지 가지며 특정 경우에 대해 각 하위 볼륨에 인스턴스를 호출 할 수 있습니다. octree는 어떤 인스턴스가 어떤 변형을 가져올 지 선택하도록 도와줍니다.


캐시 일관성을 고려해야 할 또 다른 사항은 다음과 같습니다. 큐브의 데이터가 VBO에서 배열되고 정렬되는 방식과 액세스하는 순서는 엄청납니다. 일반적으로 데이터를 잘 정렬하고 병합하기를 원합니다 (현재의 다중 경로 메모리 아키텍처로 분리 된 데이터 레이아웃으로도 좋은 성능을 제공 할 수 있지만). 그러나 액세스 패턴은 말하자면 "장소를 뛰어 넘지"말아야합니다. 귀하의 액세스를 멋지게 그룹화하십시오. 이것이 디스플레이 목록이 VBO를 능가 할 수있는 주된 이유입니다. 내용은 일정하며 드라이버는 내용을 최적 정렬되고 정렬 된 구조로 재 배열 할 수 있습니다. 이것을 실험 해봐야 할 것입니다.


당신에게 예술 게임 엔진의 현재 상태가하는 일에 대한 아이디어를 제공하려면 : DICE에서 최근 보고서는 곧 "전장 4"게임에서 가장 복잡한 장면의 단일 프레임에 의해 생성되는 것을 주장 약 2000 개 이상의 그리기 API 호출. 그건 정말 낮은 숫자입니다.

+0

우수합니다. 감사합니다. 이 테스트 응용 프로그램에서 청크 내부에 블록을 렌더링하지 못하게하는 몇 가지 기본 코드를 추가 했으므로 블록 수가 160 만에서 400k로 떨어졌지만 fps는 여전히 끔찍합니다. 내 실제 게임에서 이것은 각 블록 페이스로 확장됩니다. 나는 자바로 인스턴스화하는 방법에 대한 좋은 자습서를 찾고 있었지만, 유용한 것을 찾을 수 없다 - 나를 가리켜 줄만한 좋은 자료가 있는가? – helion3

관련 문제