2010-12-28 2 views
5

.NET Framework 4를 사용하여 C#으로 프로그래밍하고 XNA를 사용하여 타일 기반 게임을 만들려고합니다. 하나의 큰 텍스처 (256 x 4096 픽셀)가 있습니다. 타일 ​​기반 게임이라는 것을 기억하십시오.이 텍스처는 크기가 32 픽셀 x 32 픽셀 인 많은 타일을 포함하기 때문에 엄청납니다. 타일 ​​기반 게임이 어떤 전문가인지 확실히 알 것입니다. 방향은 직각 (체스 보드처럼)이며 등각이 아닙니다.Draw() 20,000 32 x 32 텍스처 또는 1 개의 큰 텍스처 20,000 시간

Game.Draw() 메서드에는 두 가지 옵션이 있는데 그 중 하나는 다른 옵션보다 훨씬 효율적입니다.

선택/방법 # 1 :

세미 의사 코드 :

public void Draw() 
    { 
     // map tiles are drawn left-to-right, top-to-bottom 
     for (int x = 0; x < mapWidth; x++) 
     { 
      for (int y = 0; y < mapHeight; y++) 
      { 
       SpriteBatch.Draw(
        MyLargeTexture, // One large 256 x 4096 texture 
        new Rectangle(x, y, 32, 32), // Destination rectangle - ignore this, its ok 
        new Rectangle(x, y, 32, 32), // Notice the source rectangle 'cuts out' 32 by 32 squares from the texture corresponding to the loop 
        Color.White); // No tint - ignore this, its ok 
      } 
     } 
    } 

캡션 : 그래서, 효율적으로, 첫 번째 방법은 참조하는 하나 개의 큰 텍스처 많은 많은 시간마다 이 큰 텍스처의 작은 사각형을 사용하여 적절한 타일 이미지를 그립니다. 효과적으로, 두 번째 방법은 많은 작은 텍스처 여러 번 드로잉되도록 :

선택/방법 # 2 :

세미 의사 코드 :

public void Draw() 
    { 
     // map tiles are drawn left-to-right, top-to-bottom 
     for (int x = 0; x < mapWidth; x++) 
     { 
      for (int y = 0; y < mapHeight; y++) 
      { 
       Texture2D tileTexture = map.GetTileTexture(x, y); // Getting a small 32 by 32 texture (different each iteration of the loop) 

       SpriteBatch.Draw(
        tileTexture, 
        new Rectangle(x, y, 32, 32), // Destination rectangle - ignore this, its ok 
        new Rectangle(0, 0, tileTexture.Width, tileTexture.Height), // Notice the source rectangle uses the entire texture, because the entire texture IS 32 by 32 
        Color.White); // No tint - ignore this, its ok 
      } 
     } 
    } 

자막.

질문 : 어떤 방법과 이유가 있습니까? 개인적으로, 나는 첫 번째 방법을 사용하는 것이 훨씬 더 효율적이라고 생각합니다. 맵에서 타일 배열에 대해 의미하는 바가 무엇인지 생각해 보면 (2000 타일로 2000 개가있는 큰지도를 생각해보십시오.) 각 Tile 객체는 소스의 X 및 Y 위치에 대해 2 개의 정수만 포함하면됩니다. 하나의 큰 텍스처 - 8 바이트의 사각형. 그러나 메서드 # 2를 사용하는 경우 맵의 타일 배열에있는 각 Tile 객체는 32 바이트 32 텍스처 (이미지 - RGBA 픽셀에 32 × 32 배의 메모리를 할당해야 함)를 저장해야하므로 타일 당 4096 바이트 그때? 그래서, 어떤 방법과 왜? 우선 순위는 속도, 메모리 부하, 효율성 또는 전문가가 믿는 것입니다.

답변

9

첫 번째 방법은 입니다. 실제로 CPU 측 데이터 구조와 관련이 없습니다. 두 경우 모두 2 바이트로 내려갈 수 있으므로 중요하지 않습니다.

첫 번째 방법이 더 빨라지는 이유는 GPU가 작동하는 방식 때문입니다. 간단히 말하면 꼭지점/삼각형 목록을 사용하여 GPU 그리기 명령을 보내십시오. 이 정점에는 다양한 데이터 (위치, 색상, 텍스처 좌표 등)가 있습니다. 결정적으로 텍스처를 지정할 수는 없습니다. 삼각형을 그리는 텍스처는 그릴 때까지 그래픽 장치에서 삼각형의 전체 목록에 대해 지정해야합니다.

SpriteBatch는 Sprite를 자동으로 일괄 처리하므로 텍스처 교환을 최소화하고 보낸 명령을 최소화합니다. 이것이 sort-by-texture를 수행하는 옵션을 갖는 이유입니다. 또한 스프라이트 시트를 사용할 수 있도록 source-rectangle 매개 변수가있는 이유는 텍스처를 변경하지 않고도 더 많은 스프라이트를 그릴 수 있기 때문입니다.

(사실, SpritBatch를 사용하지 않는 경우에도 GPU에 보내는 그리기 명령은 "배치"라고합니다. 너무 많이 보내면 "배치 제한적"이됩니다. 일괄 처리 제한 - 몇백 일괄 처리는 한도의 대략적인 추정치입니다.)

+0

종합적인 답변에 진심으로 감사드립니다. 많은 감사합니다! – Jason

2

동의합니다. GPU의 상태 변화를 최소화하기 때문에 텍스처가 작아 질수록 속도는 빨라집니다.

대부분의 타일이 프레임간에 변경되지 않는다는 점에 유의하십시오. 그래서 그것들을 모두 한 화면 크기의 렌더 타겟에 한 번 그리면 그 다음 프레임에서 한 번의 그리기 호출로 그 단일 텍스처를 다시 그립니다. 상단에 바뀌는 타일을 추가합니다.

+0

당신의 통찰력에 감사드립니다! – Jason

관련 문제