2013-02-24 3 views
0

XNA에서 "떨어지는 모래"게임을하고 있습니다. 물론, 많은 픽셀이 필요합니다. 그것은 순수하게 알고리즘을 테스트하기 위해 픽셀 당 투명한 파란색을 사용하여 시작되었습니다. 프레임 속도 (일정한 60 FPS)를 잃기 전에 약 10 만 픽셀을 화면에 표시 할 수있었습니다. 이는 필요한 것보다 많았습니다! 그러나 마침내 다른 색상의 픽셀 (파란색과 빨간색)을 추가하고 다른 변경 사항을 추가하지 않은 경우 FPS가 기하 급수적으로 떨어지고 FPS가 약 10으로 떨어지기 전에 약 10,000 픽셀 만 화면에 표시됩니다. 일부 실험을 마친 후, 스프라이트 배치가 잘못되었을 가능성이 가장 높았습니다. 스프라이트 배치가 자동으로 픽셀을 정렬하고 블렌드하기 때문에 완전히 틀릴 수도 있지만 다른 것을 생각하면 알려주십시오. 나는 두 색을 혼합하는 행위가 속도를 잃어 가고있는 것으로 생각한다. 그렇다면 어떻게 스프라이트 배치의 메소드를 사용할 수 있습니까? 아니면 완전히 기지에서 벗어나나요?SpriteBatch 정렬을 우회하는 방법? C# XNA

나는 SpriteSortMode 및 BlendMode를 사용하여 엉망으로 만들었으며 심지어 스프라이트 배치 호출 당 컬러 픽셀과 같은 그리기를 시도했지만 지금까지는 행운이 없습니다.

또한 화면에 그리는 픽셀의 좌표가 처음부터 같아서 블렌딩 등이 필요하지 않습니다. 내가 추가 색상을 추가 할 때까지 (약 60fps의 그려 100,000 픽셀)를 다시

//Game Draw Method 
    protected override void Draw(GameTime gameTime) 
    {      
     stopWatch.Start();   

     GraphicsDevice.Clear(Color.Black); 

     spriteBatch.Begin(); 

     //backgroundSprite.Draw(spriteBatch); 

     terrainSprite.Draw(spriteBatch); 

     resourceMap.Draw(spriteBatch, spriteFont);    

     frameCounter++; 

     string fps = string.Format("fps: {0}", frameRate); 

     int totalint = 0; 

     for (int i = 0; i < resourceMap.activeCoordinates.Count; i++) 
     { 
      totalint += resourceMap.activeCoordinates[i].Count; 
     } 

     string total = string.Format("resource count: {0}", totalint); 

     spriteBatch.DrawString(spriteFont, fps, new Vector2(33, 33), Color.White); 
     spriteBatch.DrawString(spriteFont, total, new Vector2(33, 45), Color.White); 
     spriteBatch.DrawString(spriteFont, totalTime, new Vector2(33, 17), Color.White);    
     spriteBatch.DrawString(spriteFont, totalTime, new Vector2(33, 17), Color.White); 


     spriteBatch.End(); 
     stopWatch.Stop(); 
     totalTime = "Draw Time:  " + stopWatch.Elapsed; 
     stopWatch = new Stopwatch(); 


     base.Draw(gameTime); 
    } 

    //resourceMap.Draw(SpriteBatch spriteBatch, SpriteFont font) from Game Draw 
    public void Draw(SpriteBatch spriteBatch, SpriteFont font) 
    { 
     //spriteBatch.End(); 
     //this was originally one for loop to draw all pixels, but was separated to draw each different color pixel after discovering performance issue 
     for (int c = 0; c < activeCoordinates.Count(); c++) 
     { 
      //spriteBatch.Begin(); 
      for (int i = 0; i < activeCoordinates[c].Count; i++) 
      { 
       mapArray[(int)activeCoordinates[c][i].X][(int)activeCoordinates[c][i].Y].Draw(spriteBatch); 
      } 
      //spriteBatch.End(); 
     } 
     //spriteBatch.Begin(); 
     spriteBatch.DrawString(font, timeInMilli, new Vector2(33, 0), Color.White); 
    } 

는, 코드에 만든 유일한 변화가 그려 질 픽셀의 목록에 다른 색상을 추가, 그래서 여기 코드는 좋은 일하고 있었다 .

도움 주셔서 감사합니다.

+0

코드는 draw 메서드가있는 for 루프만큼 간단합니다. 설명만큼이나 도움이되어서는 안되지만 거기에 가면 ^^. – Colton

+1

'mapArray [] []. Draw '가 무엇이든간에 코드를 추가 할 수 있습니까? 각 픽셀을 개별 스프라이트로 그리는 것이 어쨌든이 잘못된 해결책 일 가능성이 높습니다. –

+1

나는 모든 모래 입자에 대해 하나의 텍스처이지만 다른 색상으로 착색 된 흰색 픽셀을 그려서 문제를 해결할 수 있다고 생각합니다. 문제가 게시하지 않은 다른 항목에도있을 수 있지만 프레임 속도가 올라갈 수 있습니다. 하지만 그렇습니다. 각 모래 입자에 대해 하나의 픽셀 텍스처를 그리는 것은 대단히 느린 접근법입니다. 인터넷 검색 * 가루 * 게임을 시도하고 그들이 그것을 어떻게. – user1306322

답변

1

좋아, 내가 할 수있는 최선의 답변을 제공 하겠지만 게시 한 코드의 양에 따라 제한됩니다. 우선, 성능에 영향을 미치는 다양한 요인에 대한 개요는 this answer으로 안내합니다.

SpriteBatch과 관련하여 발생할 수있는 문제는 너무 많은 배치를 시작해야한다는 것입니다. 텍스처를 바꿀 때마다 배치를 시작해야합니다. 다른 픽셀에 대해 다른 텍스처를 사용하는 것처럼 들리며, 임의의 순서로 그립니다.

SpriteBatch (SpriteSortMode.Texture) 내의 텍스처로 정렬하는 것은 그 자체로 값 비싼 작업이 될 수 있습니다. 텍스처가 비슷한 스프라이트를 그룹화하는 코드는 느리거나 잘못 될 수 있습니다.하지만 사용자가 지정한 코드로는 알 수 없습니다.

많은 텍스처를 사용하는 것이 아니라 단일의 흰색 텍스처를 사용하고 tint 매개 변수를 사용하여 각 스프라이트를 원하는 색상으로 동적으로 색조를 지정하는 것이 좋습니다. 그런 다음 모든 스프라이트를 단일 배치로 보낼 수 있습니다.

BUT뿐만 아니라 수많은 스프라이트에 대한 버텍스를 설정하기위한 많은 처리가 있기 때문에 실제로 얼마나 많은 데이터가 GPU로 보내지는지 고려해야합니다. 각 스프라이트에는 4 개의 정점이 있습니다. 각 정점에는 위치, 색상 및 텍스처 좌표가 있습니다. 픽셀 당 무려 96 바이트입니다. 그리고 그 모든 것들이 각 프레임에 GPU로 전송되어야합니다!

텍스처는 반면에 4 바이트입니다. 그래서 그것은 일까요? 당신은 당신이이보다 Texture2D.SetData 더를 호출하는 경우, 모든

첫째 :

은 속도를 저하 될 수있는 두 가지가 있습니다.SetData을 호출 할 때마다 상당한 양의 오버 헤드가 필요합니다. 픽셀 당 한 번 호출하면 속도가 매우 느려집니다. 대신 전체 이미지에 대해 한 번 호출하십시오. 이 으로 충분해야합니다.이 테스트를 직접 해보지는 않았지만 사용하기에 충분히 빠릅니다.

다른 가능성은 GPU에 심도있는 파이프 라인 (하드웨어에 따라 다름)이 있고 프레임 N + 1에 대해 프레임을 업데이트하려고 할 때 텍스처 N을 렌더링하는 것입니다. 이렇게하면 새로운 변경 사항을 적용하기 전에 GPU가 프레임 N 렌더링을 완료하게됩니다. GPU를 많이 사용하는 다른 작업을 수행하거나 그래픽 드라이버가 어리석은 일을하지 않으면 문제가 발생하지 않을 수도 있습니다.

+0

이 모든 것들은 제가 불행하게도 이미 고쳐 놓았던 문제 였지만, 필자가 필요로했던 최종 수정은 전체 텍스처를 리셋하는 대신 한 번에 한 픽셀 씩 텍스처 데이터를 설정하는 것이 었습니다. 한 번에 하나의 픽셀을 설정하는 방법에 대한 조사가 끝난 후, 내가 발견 한 모든 것은 불가능하다고 말하는 게시물이었습니다. 그런 다음 마침내 어떻게하는지 알아 냈습니다! 문제는 해결되었지만 많은 중요한 정보를 다루었 기 때문에 대부분 올바른 답을 얻었습니다. – Colton