2013-12-08 3 views
0

XNA 4.0 용 그래픽 엔진에서 작업 중이며 어떤 해결책을 찾을 수없는 문제가 발생했습니다. 현재 셰이더를 사용하여 조명 효과를 구현하려고합니다. 그래픽 엔진도 입자 엔진으로 구성되어 있으므로 성능을 최소한으로 고려해야합니다. 이 두 가지를 조합하면 문제가 발생합니다.XNA 4.0 하나의 일괄 처리에서 여러 효과 사용

우선, 나는 많은 독서와 연구를 해왔다. 그리고 내가 이해하는 바에 따르면, 당신은 더 낮은 무승부로 더 나은 성적을 얻는다. 그리기 호출을 통해 스프라이트 배치가 실제 지오메트리와 텍스처를 GPU로 보낼 때를 의미합니다. 따라서 하나의 일괄 처리 내에서 가능한 한 많이 그려야합니다.

이제 문제가 발생합니다. 내 엔진 드로잉 메서드에 대한 2 오버로드가 있습니다.

public static void Draw(Texture texture) 
{ 
    // Call spriteBatch.Draw(...); 
} 

public static void Draw(Light light) 
{ 
    // Call spriteBatch.Draw(...); 
} 

첫 번째 오버로드는 기본 셰이더로 일반 텍스처를 그릴 것입니다. 두 번째 오버로드는 다른 셰이더를 사용하는 광원을 그립니다. 내가 뭘하고 싶은 것은 그러나

public static void Draw(Texture texture) 
{ 
    // Use default shader 
    // Call spriteBatch.Draw(...); 
} 

public static void Draw(Light light) 
{ 
    // Use light shader 
    // Call spriteBatch.Draw(...); 
} 

의의 SpriteBatch 나는 효과가이 작업을 수행하려고 그렇게 때문에, 한 번에 여러 쉐이더를 지원하지 않는 대신 전달합니다

public static void Draw(Texture texture) 
{ 
    effect.CurrentTechnique.Passes[0].Apply(); 
    // Call spriteBatch.Draw(...); 
} 

public static void Draw(Light light) 
{ 
    effect.CurrentTechnique.Passes[1].Apply(); 
    // Call spriteBatch.Draw(...); 
} 

이 didn를 ' SpriteBatch.Draw()가 호출 될 때 쉐이더가 사용되지 않고 대신 spriteBatch.End()가 호출 될 때 쉐이더가 사용되지 않기 때문에 작동합니다. 따라서 위의 코드는 내가 마지막으로 적용한 패스로 모든 것을 렌더링했습니다.

public static void Begin() 
{ 
    spriteBatchColor.Begin([...], null); // Default shader. 
    spriteBatchLight.Begin([...], effect); // Light shader. 
} 

public static void Draw(Texture texture) 
{ 
    // Call spriteBatchColor.Draw(...); 
} 

public static void Draw(Light light) 
{ 
    // Call spriteBatchLight.Draw(...); 
} 

public static void End() 
{ 
    spriteBatchColor.End(); 
    spriteBatchLight.End(); 
} 

이 실제로 작동 않았다,하지만 내 계층의 깊이가 완전히 spriteBatchLight.End()가 마지막으로 호출되기 때문에 이상한하지 않은, 엉망이있어 :

내 세 번째 시도는 2 SpriteBatches를 사용하는 것이 었습니다 따라서 spriteBatchColor가 그렸던 모든 것 위에 항상 그려집니다.

SpriteSortMode를 SpriteSortMode.Immediate로 설정할 수 있다는 것을 알고 있지만 그 모드가 모든 것을 직접적으로 끌어들이므로 큰 성능 페널티가 발생합니다. 이 경우 성능이 매우 중요하므로 가능한 한 GPU 그리기 호출을 최소화하여 최적화하고 싶습니다. SpriteSortMode.Immediate는 나를위한 옵션이 아닙니다./

내가이 다른 효과/기술을 사용할 수있는 방법이 있나요 일괄을 전달합니다

그래서, 내 질문은? 아니면 두 가지 SpriteBatches를 사용할 수있는 방법이 있습니까? 그렇다면 마지막 드로우를 만들 때 결합하여 레이어 깊이가 엉망이되지 않도록 할 수 있습니까?

+0

나는 그것이 가능해야한다고 생각,하지만 난 당신이 다른 용도로 다시 사용하기 전에 장치의 일부 주를 재설정 할 필요가 있다고 생각합니다. http://blogs.msdn.com/b/shawnhar/archive/2010/06/18/spritebatch-and-renderstates-in-xna-game-studio-4-0.aspx?PageIndex=2를 확인하십시오. –

+0

' 무슨 뜻인지 모르겠다. 설명하고 싶니? –

답변

1

와우, 죽은 잘못이기 때문에 내 이전 대답을 무시하십시오.

실제 게임을 수행하는 방법은 기본 게임 클래스에 List<RenderTarget2D>을 생성하고이를 드로잉 인 함수/클래스로 전달하는 것입니다. 엔진 그리기 방법에

:

public static void Draw(Texture texture, List<RenderTarget2D> targetList) 
{ 
    RenderTarget2D target = new RenderTarget2D(...); 

    //Tell spriteBatch to draw to target instead of the screen 
    spriteBatch.GraphicsDevice.SetRenderTarget(target); 

    //Make the renderTarget's background clear 
    spriteBatch.GraphicsDevice.Clear(new Color(0,0,0,0)) 

    spriteBatch.Begin(); 
    //Apply effect and draw 
    spriteBatch.End(); 

    targetList.Add(target); 
} 

그런 다음 당신은 화면에 각 텍스처를 그립니다.

게임에서 방법을 그립니다 :

void Draw() 
{ 
    List<RenderTarget2D> targetList = new List<RenderTarget2D>(); 

    engine.Draw(texture, targetList); 
    engine.Draw(light, targetList); 

    //Tell spriteBatch to draw to the screen 
    spriteBatch.GraphicsDevice.SetRenderTarget(null) 

    //Make the screen background black 
    spriteBatch.GraphicsDevice.Clear(Color.Black) 

    spriteBatch.Begin(); 
    //Draw each target in target list to screen 
    spriteBatch.End(); 
}