이것에 대한 정답은 ContentPipeline을 건너 뛰고 Texture2D.FromStream을 사용하여 런타임에 텍스처를로드하는 것 같습니다. 이 방법은 PC에서 잘 작동하며 약간의 성능 저하가 있더라도 출시 날짜에 가까워지면 최적화 할 수 있습니다. 현재로서는 에디터와 게임 모두에 대해 컨텐츠를 동적으로 수정할 수있는 능력이 필요합니다. 내용이 고정되면 ContentPipeline으로 돌아가서이를 최적화 할 수 있습니다.
이 경로를 선택 했으므로 실제로 Texture2D.FromStream
두 가지 이유로 사용 하는 것만 큼 간단하지 않다는 경고를 표시해야합니다 .
문제 # 1-사전 곱셈 알파 지원 부족
XNA4는 이제 기본적으로 사전 곱셈 된 알파 형식의 색상으로 텍스처를 처리합니다. 콘텐츠 파이프 라인을 통해 텍스처를로드하면 해당 처리가 자동으로 수행됩니다. 불행히도 Texture2D.FromStream
같은 일을하지 않으므로 어느 정도의 투명성이 필요한 텍스처가로드되고 잘못 렌더링됩니다. 아래는 문제를 설명하는 스크린 샷입니다.
따라서 올바른 결과를 얻으려면 처리를 직접 수행해야합니다. 내가 보여줄 방법은 GPU를 사용하여 처리를 수행하므로 매우 빠릅니다. 이 위대한 기사를 기반으로했다 . 물론 SpriteBatch
이전 NonPremultiplyAlpha 모드에서 렌더링 하도록 지시 할 수도 있지만 실제로는 권장하지 않습니다.
문제 # 2-지원되지 않는 형식
콘텐츠 파이프 라인은보다 많은 형식을 지원합니다 Texture2D.FromStream
. 특히 Texture2D.FromStream
png, jpg 및 gif 만 지원합니다. 반면 컨텐츠 파이프 라인은 bmp, dds, dib, hdr, jpg, pfm, png, ppm 및 tga를 지원합니다. 당신이 usuported 형식을로드하려고하면 통해 Texture2D.FromStream
당신은 얻을 것이다 InvalidOperationException
약간의 추가 정보.
실제로 엔진에서 bmp 지원이 필요했기 때문에 특정 경우에는 제대로 작동하는 것으로 나타났습니다. 그래도 다른 형식에 대해서는 모르겠습니다. 내 방법의 System.Drawing
장점은 프로젝트 보다 어셈블리에 대한 참조를 추가해야한다는 것 입니다. GDI를 Image.FromStream
보다 많이 지원하는 GDI를 사용하기 때문 Texture2D.FromStream
입니다.
bmp 지원에 신경 쓰지 않는다면 내 솔루션의 해당 부분을 쉽게 삭제하고 미리 곱한 알파 처리를 수행 할 수 있습니다.
솔루션-단순 버전 (느리게)
우선, bmp 지원에 신경 쓰지 않는다면 가장 간단한 해결책이 있습니다. 이 예제에서 처리 단계는 전적으로 CPU에서 수행됩니다. 아래에 보여 줄 대안보다 약간 느리지 만 (두 솔루션을 벤치 마크 했음) 이해하기 쉽습니다.
public static Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream)
{
Texture2D texture = Texture2D.FromStream(graphicsDevice, stream);
Color[] data = new Color[texture.Width * texture.Height];
texture.GetData(data);
for (int i = 0; i != data.Length; ++i)
data[i] = Color.FromNonPremultiplied(data[i].ToVector4());
texture.SetData(data);
return texture;
}
bmp에 관심이 있다면 먼저 GDI로 이미지를로드 한 다음 PNG로 전달하기 전에 내부적으로 PNG로 변환해야합니다 Texture2D.FromStream
. 이를 수행하는 코드는 다음과 같습니다.
// Load image using GDI because Texture2D.FromStream doesn't support BMP
using (Image image = Image.FromStream(stream))
{
// Now create a MemoryStream which will be passed to Texture2D after converting to PNG internally
using (MemoryStream ms = new MemoryStream())
{
image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
ms.Seek(0, SeekOrigin.Begin);
texture = Texture2D.FromStream(_graphicsDevice, ms);
}
}
솔루션-복잡한 버전 (빠른)
마지막으로 프로젝트에서 사용하는 방법은 GPU를 사용하여 처리하는 것입니다. 이 방법에서는 렌더링 대상을 만들고 일부 블렌드 상태를 올바르게 설정 한 다음 SpriteBatch로 이미지를 두 번 그려야합니다. 마지막으로 전체 RenderTarget2D를 살펴보고 RenderTarget2D가 휘발성이고 백 버퍼 크기를 변경하는 것과 같이 살아남지 않으므로 사본을 만드는 것이 더 안전하므로 내용을 별도의 Texture2D 객체로 복제합니다.
재미있는 점은이 모든 것조차도 내 테스트 에서이 접근법이 CPU 접근법보다 약 3 배 빠르게 수행되었다는 것입니다. 따라서 각 픽셀을 살펴보고 색상을 직접 계산하는 것보다 확실히 빠릅니다. 코드가 약간 길어서 pastebin에 넣었습니다.
http://pastie.org/3651642
해당 클래스를 프로젝트에 추가하고 다음과 같이 간단하게 사용하십시오.
TextureLoader textureLoader = new TextureLoader(GraphicsDevice);
Texture2D texture = textureLoader.FromFile("Content/texture.png");
참고 : TextureLoader
전체 게임에 대해 하나의 인스턴스 만 작성 하면됩니다. 또한 BMP 수정 프로그램을 사용하고 있지만 많은 성능이 필요하지 않거나 needsBmp
매개 변수를 false로 남겨두면 제거 할 수 있습니다.