2D 게임에서 큰 비디오 메모리 요구 사항을 어떻게 해결합니까?


40

2D 게임에서 큰 비디오 메모리 요구 사항을 어떻게 해결합니까?


우리는 allegro C / C ++에서 2D 게임 (Factorio)을 개발하고 있으며 게임 콘텐츠가 증가함에 따라 비디오 메모리 요구 사항이 증가하는 문제에 직면하고 있습니다.

현재 사용할 이미지에 대한 모든 정보를 수집하고 가능한 한 많은 이미지를 자르고 가능한 한 큰 아틀라스로 구성합니다. 이러한지도 책은 비디오 메모리에 저장되며 크기는 시스템 제한에 따라 다릅니다. 현재 일반적으로 최대 8192x8192의 2 개 이미지이므로 256Mb ~ 512Mb 비디오 메모리가 필요합니다.

이 시스템은 일부 사용자 정의 최적화와 렌더 및 업데이트 스레드를 분할하여 60fps로 화면에 수만 개의 이미지를 그릴 수 있으므로 매우 효과적입니다. 화면에 많은 물체가 있으므로 큰 축소를 허용하는 것이 중요합니다. 더 추가하고 싶을 때 비디오 메모리 요구 사항에 문제가 생길 수 있으므로이 시스템을 유지할 수 없습니다.

우리가 시도하고 싶었던 것 중 하나는 가장 일반적인 이미지를 가진 하나의 아틀라스를, 두 번째는 캐시로 사용하는 것입니다. 필요에 따라 이미지가 메모리 비트 맵에서 이동됩니다. 이 방법에는 두 가지 문제가 있습니다.

  1. 알레그로에서 메모리 비트 맵에서 비디오 비트 맵으로의 드로잉은 매우 느립니다.
  2. allegro에서는 메인 스레드 이외의 비디오 비트 맵으로 작업 할 수 없으므로 실제로 사용할 수 없습니다.

추가 요구 사항은 다음과 같습니다.

  • 게임은 결정 론적이어야하므로 성능 문제 /로드 시간은 게임 상태를 절대 변경할 수 없습니다.
  • 이 게임은 실시간이며 곧 멀티 플레이어가 될 것입니다. 우리는 모든 비용에서 가장 작은 말 더미도 피해야합니다.
  • 게임의 대부분은 하나의 지속적인 열린 세상입니다.

테스트는 1x1에서 300x300 크기의 배치마다 10,000 개의 스프라이트를 배치 할 때마다 모든 구성에 대해 여러 번 구성되었습니다. Nvidia Geforce GTX 760에서 테스트를 수행했습니다.

  • 소스 비트 맵이 개별 비트 맵 (아틀라스 변형)간에 변경되지 않은 경우 비디오 비트 맵 대 비디오 비트 맵 드로잉은 스프라이트 당 0.1us를 소비했습니다. 크기는 중요하지 않았다
  • 비디오 비트 맵을 비디오 비트 맵 드로잉으로, 소스 비트 맵이 드로잉간에 전환되었지만 (아틀라스가 아닌 변형) 스프라이트 당 0.56us가 사용되었습니다. 크기도 중요하지 않았습니다.
  • 비디오 비트 맵 드로잉에 대한 메모리 비트 맵은 실제로 의심 스러웠습니다. 1x1에서 200x200까지의 크기는 비트 맵당 0.3us를 사용하므로 너무 느리지 않습니다. 더 큰 크기의 경우 시간이 201x201의 경우 9us에서 291x291의 경우 3116us로 매우 크게 증가하기 시작했습니다.

아틀라스를 사용하면 성능이 5보다 크게 증가합니다. 렌더링에 10ms가 있고 아틀라스를 사용하면 프레임 당 100 000 스프라이트로 제한되며 프레임이 없으면 20 000 스프라이트로 제한됩니다. 이것은 문제가 될 것입니다.

또한 그림자에 대한 비트 맵 압축 및 1bpp 비트 맵 형식을 테스트하는 방법을 찾으려고했지만 알레그로에서이를 수행하는 방법을 찾을 수 없었습니다.


1
귀하의 게임을 좋아하는 팬인 저는 Indiegogo 캠페인을 후원했습니다. 나는 몇 개월마다 그것에 폭식. 지금까지 좋은 일! 사이트에서 다루지 않은 "사용할 기술"질문을 제거했습니다. 나머지 질문은 여전히 ​​넓습니다. 더 구체적인 내용이 있으면 범위를 좁히십시오.
MichaelHouse

도와 주셔서 감사합니다. 그렇다면 어떤 기술을 사용할 것인지 물어볼 수있는 곳은 어디입니까? 특정 엔진 권장 사항에 대한 답변을 찾고 있지는 않지만 2D 엔진을 심도있게 비교하고 성능 및 사용성 테스트를 포함하여 하나씩 수동으로 검사하는 데는 시간이 걸릴 수 있습니다.
Marwin

"사용할 기술"과 같은 질문을 할 수있는 곳 은 이 페이지 하단을 확인하십시오 . 당신은 완전히 유효하고 합리적인 질문이 있습니다. 그것은 우리가이 사이트에서 다루는 질문의 유형이 아닙니다. 특정 엔진을 찾고 있지 않더라도 "X를 수행하는 기술이 있습니까?"라는 질문에 대답 할 수있는 유일한 방법입니다. 누군가 "예"라고 대답하고 특정 권장 사항을 제시하지는 않지만 그다지 도움이되지는 않습니다. 행운을 빕니다!
MichaelHouse

2
텍스처를 압축하고 있습니까?
GuyRT

3
@Marwin, 압축 텍스처는 필요한 메모리 대역폭을 감소시키기 때문에 압축되지 않은 텍스처보다 훨씬 더 성능이 좋을 수 있습니다 (대역폭이 훨씬 낮은 모바일 플랫폼에서 특히 그렇습니다). 텍스처를 압축하면 엄청난 양의 메모리를 절약 할 수 있습니다. 실제로 유일한 단점은 필연적으로 소개되는 인공물입니다.
GuyRT

답변:


17

RTS (KaM Remake)와 비슷한 경우가 있습니다. 모든 유닛과 주택은 스프라이트입니다. 유닛과 주택 및 지형에는 18,000 개의 스프라이트와 팀 색상 (마스크로 적용됨)에 대해 ~ 6,000이 추가됩니다. 길게 늘여서 글꼴에 ~ 30,000 문자가 사용되었습니다.

따라서 사용중인 RGBA32 아틀라스에 대한 최적화가 있습니다.

  • 스프라이트 풀을 여러 개의 작은 아틀라스로 먼저 나누고 다른 답변에서 다룰 때 필요에 따라 사용하십시오. 또한 각 아틀라스에 대해 다른 최적화 기술을 개별적 으로 사용할 수 있습니다 . 나는 당신이 그런 거대한 질감으로 포장 할 때 일반적으로 바닥에 사용되지 않는 영역이있을 때 낭비되는 RAM을 조금 덜 가질 것이라고 생각합니다.

  • 팔레트 텍스처 를 사용해보십시오 . 셰이더를 사용하는 경우 셰이더 코드에서 팔레트를 "적용"할 수 있습니다.

  • RGBA8 대신 RGB5_A1 을 사용하는 옵션을 추가 할 수 있습니다 (예를 들어, 체커 보드 그림자가 게임에 적합한 경우). 가능하면 8 비트 알파를 피하고 RGB5_A1 또는 이와 유사한 형식 (RGBA4와 같은)을 사용하면 공간의 절반을 차지합니다.

  • 당신이 있는지 확인 단단히지도 책에 스프라이트를 포장 필요한 경우, (빈 알고리즘을 포장 참조) 회전 스프라이트를하고 마름모 스프라이트 투명 모서리를 겹칠 수 있는지;

  • 당신은 시도 할 수 있습니다 하드웨어 압축 포맷 (등 DXT, S3TC를) - 그들이 극적으로 RAM 사용량을 줄일 수 있지만, 압축 아티팩트를 확인할 수 있습니다 - 일부 이미지에 차이가 (당신이 선택적으로 첫 번째 글 머리에 설명이 사용할 수 있습니다) 눈에 띄지 할 수있다, 그러나 일부에-매우 발음. 압축 형식이 다르면 아티팩트가 다르므로 아트 스타일에 가장 적합한 것을 선택할 수 있습니다.

  • 큰 스프라이트를 (수동이 아니라 텍스처 아틀라스 패커 내에서) 정적 배경 스프라이트와 애니메이션 파트를위한 작은 스프라이트 로 분할하는 것을 살펴보십시오 .


2
DXT를 사용하는 데 +1하면 매우 좋습니다. 압축률이 높고 GPU에서 직접 사용하므로 오버 헤드가 최소화됩니다.

1
나는 dxt에 동의합니다. DXT1과 크기는 같지만 품질은 더 높은 DXT7 지원 (DX11 + 하드웨어)을 요청할 수도 있습니다. 그러나 텍스처는 두 배 (하나는 DXT7과 하나는 DXT1)를 갖거나로드하는 동안 압축 / 압축 해제해야합니다.
Programmdude

5

우선, 더 작은 텍스처 아틀라스를 사용해야합니다. 텍스처가 적을수록 메모리 관리가 더 어려워지고 엄격 해집니다. 아틀라스 크기는 1024를 제안합니다.이 경우 2 대신 128 텍스처가 있거나 2048이되면 32 텍스처가 필요하므로 필요에 따라로드 및 언로드 할 수 있습니다.

대부분의 게임은 레벨 경계를 설정하여이 자원 관리를 수행하는 반면, 로딩 화면에는 다음 레벨에서 더 이상 필요하지 않은 모든 자원이 언로드되고 필요한 자원이로드됩니다.

또 다른 옵션은 주문형 로딩으로, 레벨 경계가 원치 않거나 단일 레벨이 너무 커서 메모리에 맞지 않을 경우 필요합니다. 이 경우 게임은 향후 플레이어가 볼 내용을 예측하여 백그라운드에로드하려고합니다. (예 : 플레이어로부터 현재 2 화면 떨어진 물건) 더 이상 오랫동안 사용하지 않은 물건은 언로드됩니다.

그러나 한 가지 문제가 있는데, 게임이 예상 할 수 없었던 예기치 않은 일이 발생하면 어떻게됩니까?

  • 모든 필요한 물건이로드 될 때까지 당황하고 로딩 화면이 표시됩니다. 이는 경험에 지장을 줄 수 있습니다.
  • 사전로드 된 모든 항목에 대해 저해상도 스프라이트를 사용하여 고해상도 스프라이트가로드되는 즉시 게임을 계속하고 교체하십시오. 이것은 플레이어에게 저렴하게 보일 수 있습니다.
  • 게임 플레이에 영향을 미치고 필요한만큼 이벤트를 지연시킵니다. 예를 들어 그래픽이로드 될 때까지 적을 스폰하지 마십시오. 해당 전리품에 대한 모든 그래픽이로드되기 전에 보물 상자를 열지 마십시오.

생략 한 요구 사항 중 일부를 추가했습니다. 로딩 화면 또는 모든 종류의 로딩이 불가능합니다. 렌더 준비 및 게임 업데이트에서 일반적으로 이미 대부분의 시간이 사용되는 동안 모든 것은 백그라운드에서 또는 개별 틱 (각각 15ms 미만) 사이에서 수행해야합니다. 어쨌든 작은 부품으로 분할하면 스위칭에 약간의 유연성이 추가 될 수 있으므로 확실히 빠릅니다. 문제는 렌더링하는 동안 소스 비트 맵을 전환하면 렌더링 속도가 느려지므로 렌더링시 성능이 얼마나 저하 되는가입니다. 나는 얼마나 많은지를 말하기 위해 정확한 측정을해야 할 것입니다.
Marwin

@Marwin 성능에 미치는 영향은 그렇습니다. 그러나 2D를 다루기 때문에 여전히 문제가되지 않아야합니다. 렌더링이 현재 프레임 당 1ms가 걸리고 더 작은 텍스처를 사용하는 데 갑자기 2ms가 걸리면 여전히 60FPS에 도달 할 수있을 정도로 빠릅니다. (16ms)
API-Beast

@Marwin Multiplayer는 까다로운 비즈니스입니다. 항상 그렇습니다. 거기서 타협해야 할 것입니다. 인터넷을 통해 데이터를 전송해야하고, 패키지가 손실되거나, 핑이 갑자기 급등 할 수 있기 때문에, 더듬기가 발생할 수 있습니다. 더듬기가 불가피하므로 더 중요한 것은 네트워크 모델 자체를 더듬기에 저항하는 것입니다. 기다리는 시간 및 다른 플레이어를 기다리는 방법을 알고 있습니다.
API-Beast

안녕하세요, 멀티 플레이어에서 더듬을 거의 피할 수 있습니다. 현재 해당 분야에서 일하고 있으며, 좋은 계획이 있다고 생각합니다. 나중에 자세히 조사한 내용을 설명하는 내 자신의 질문을 게시하고 대답 할 수도 있습니다. 놀랍지 만 렌더링 시간은 실제로 문제입니다. 렌더링 속도를 높이기 위해 많은 최적화를 수행했습니다. 메인 렌더는 이제 별도의 스레드와 다른 작은 조정으로 이루어집니다. 최대 줌에서 플레이어는 동시에 수만 개의 스프라이트를 쉽게 볼 수 있습니다. 그리고 나중에 더 높은 줌 레벨을 허용하고 싶습니다.
Marwin

적절한 배치를 사용하는 경우 @Marwin Hm, 10k 개체는 일반적으로 PC 또는 최신 랩톱에서 문제가되지 않아야합니다. 렌더링 코드를 프로파일 링했습니까?
API-Beast

2

와우, 내가 생각하는 3D 모델에서 생성 된 엄청난 양의 애니메이션 스프라이트입니까?

이 게임을 원시 2D로 만들면 안됩니다. 원근을 고정하면 재미있는 일이 발생하며, 사전 렌더링 된 스프라이트와 배경을 일부 렌더링 게임에서 많이 사용 된 라이브 렌더링 된 3D 모델과 완벽하게 혼합 할 수 있습니다. 가장 자연스러운 방법처럼 보이는 훌륭한 애니메이션을 원한다면. 3D 엔진을 가져 와서 등각 투시를 사용하도록 구성하고 스프라이트를 계속 사용하는 객체를 이미지가있는 단순한 평면으로 렌더링합니다. 3D 엔진으로 텍스처 압축을 사용할 수 있습니다. 그 자체만으로도 큰 발전입니다.

화면에 거의 모든 것을 동시에 가질 수 있기 때문에로드 및 언로드가 많은 도움이 될 것이라고 생각하지 않습니다.


2

먼저 RGBA4444 또는 DXT 압축 등 게임의 비주얼에 만족하면서도 가장 효율적인 텍스처 형식을 찾으십시오. DXT 알파 압축 이미지로 생성 된 인공물에 만족하지 않으면 실행 가능할 것입니다 알파에 대해 4 비트 또는 8 비트 그레이 스케일 마스킹 텍스처와 결합 된 색상에 DXT1 압축을 사용하여 이미지를 불투명하게 만들려면? GUI를 위해 RGBA8888을 유지한다고 상상해보십시오.

나는 당신이 결정한 형식을 사용하여 작은 질감으로 나누는 것을 옹호합니다. 항상 화면에 표시되어 항상로드되는 항목을 결정하십시오. 이는 지형 및 GUI 아틀라스 일 수 있습니다. 그런 다음 일반적으로 함께 렌더링되는 나머지 항목을 가능한 많이 분리합니다. 나는 당신이 PC에서 50-100 무승부 전화로 올라가도 너무 많은 성능을 잃을 것이라고 생각하지 않지만 내가 틀렸다면 나를 바로 잡으십시오.

다음 단계는 위에서 지적한대로 이러한 텍스처의 밉맵 버전을 생성하는 것입니다. 단일 파일로 저장하지 않고 별도로 저장합니다. 따라서 각 파일의 1024x1024, 512x512, 256x256 등 버전으로 끝나고 표시하려는 가장 낮은 수준의 세부 정보에 도달 할 때 까지이 작업을 수행합니다.

이제 별도의 텍스처가 있으므로 현재 확대 / 축소 레벨에 대한 텍스처를로드하고 사용하지 않는 경우 텍스처를 언로드하는 LOD (Level of Detail) 시스템을 구축 할 수 있습니다. 렌더링중인 항목이 화면에 없거나 현재 확대 / 축소 수준에 필요하지 않은 경우 텍스처가 사용되지 않습니다. 업데이트 / 렌더 스레드와 별도로 스레드에서 비디오 RAM에 텍스처를로드하십시오. 필요한 텍스처가로드 될 때까지 가장 낮은 LOD 텍스처를 표시 할 수 있습니다. 때때로 낮은 디테일 / 높은 디테일 텍스처간에 눈에 띄는 전환이 발생할 수 있지만 맵을 이동하면서 매우 빠르게 축소 / 확대 할 때만 가능하다고 생각합니다. 현재 메모리 제약 조건 내에서 가능한 한 많이 이동하거나 확대 / 축소하고로드 할 위치를 미리로드하여 시스템을 지능적으로 만들 수 있습니다.

그것이 도움이되는지 테스트하기 위해 일종의 테스트입니다. 필연적으로 LOD 시스템이 필요한 극단적 인 줌 레벨을 얻는다고 생각합니다.


1

가장 좋은 방법은 텍스처를 여러 파일로 분할하고 필요에 따라로드하는 것입니다. 아마도 문제는 완전한 3D 장면에 필요한 더 큰 텍스처를로드하려고하고 Allegro를 사용하고 있다는 것입니다.

큰 축소를 적용하려면 밉맵을 사용해야합니다. 밉맵은 객체가 카메라에서 충분히 멀리 떨어져있을 때 사용되는 텍스처의 저해상도 버전입니다. 즉, 8192x8192를 4096x4096으로 저장 한 다음 2048x2048 등으로 저장할 수 있으며 화면에서 스프라이트가 작을수록 더 낮은 해상도로 전환 할 수 있습니다. 로드 할 때 텍스처를 별도의 텍스처로 저장하거나 크기를 조정할 수 있습니다 (그러나 런타임 중에 밉맵을 생성하면 게임의로드 시간이 길어집니다).

적절한 관리 시스템은 필요할 때 필요한 파일을로드하고 아무도 파일을 사용하지 않을 때 리소스를 해제합니다. 리소스 관리는 게임 개발에서 중요한 주제이며 관리가 전혀없는 단일 텍스처에 대한 간단한 좌표 매핑으로 관리를 줄입니다.


1
파일로 분할하면 HDD의 파일을 의미합니까? 필자는 초보자를 위해 모든 그림을 RAM에 저장할 수 있으며 메모리 비트 맵에서 비디오 비트 맵으로 복사하는 것이 현재 너무 느리므로 HDD에서로드하는 것이 훨씬 느릴 것이라고 가정합니다. vmp에서 여전히 가장 큰 해상도를 갖기 때문에 mpaps를 갖는 것이 도움이되지 않습니다.
Marwin

예, 모든 것을로드 할 필요는 없으며 사용하는 것만로드해야합니다. VRAM에로드 된 텍스처의 픽셀을 변경할 때마다 단일 픽셀을 수정하기 위해 시스템은 전체 텍스처를 RAM으로 이동해야합니다. VRAM으로 다시 이동하십시오. 단일 텍스처에 모든 것이 있으면 256MB를 RAM으로 이동 한 다음 다시 VRAM으로 다시 이동시켜 전체 컴퓨터를 잠급니다. 다른 파일과 텍스처로 분리하는 것이 올바른 방법입니다.
Pablo Ariel

메모리로 복사 및 램으로 다시 복사를 트리거하는 텍스처 수정은 영구 비트 맵에만 적용되며 캐시는 지속적으로 설정되지 않으며 유일한 단점은 디스플레이가 손실되거나 발견 될 때이를 새로 고칠 필요가 있습니다. 그러나 allegro에서는 vram에서 메모리 비트 맵 (게임 미리보기 저장)으로의 640X480 그림의 단순한 사본조차도 꽤 오랜 시간이 걸립니다.
Marwin

1
그림 자체를 최적화하지 않고 하나의 큰 질감으로 모든 것을 가져야합니다. 개별 스프라이트 사이의 컨텍스트 전환 효과로 인해 적어도 allegro에서 렌더링 속도가 너무 느려집니다. 내가 틀리지 말아라. 그러나 당신은 내가이 질문에서 내가 요구하는 것을 할 것을 모호하게 제안하고 있기 때문에 당신은 분명한 선장이다.
Marwin

1
이 밉맵 텍스처를 다른 파일에 넣으면 플레이어가 확대 할 때 모든 아틀라스를 다시로드해야합니다. 엔진에는 최대 단위가 거의 없기 때문에 처리 방법을 알 수 없습니다.
Marwin

0

zlib로 압축하고 각 아틀라스에 대한 압축에서 스트리밍 할 수있는 더 많은 아틀라스 파일을 만드는 것이 좋습니다. 더 많은 아틀라스 파일과 더 작은 크기의 파일을 가짐으로써 비디오 메모리에서 활성 이미지 데이터의 양을 제한 할 수 있습니다. 또한 트리플 버퍼 메커니즘을 구현하여 각 드로우 프레임을 더 빨리 준비하고 더 빨리 완료되어 더듬기가 화면에 나타나지 않도록 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.