속도에 따라 흐릿한 스프라이트 렌더링


9

게임에 속도를 추가 한 후 텍스처가 왜곡되는 느낌이 듭니다. 마침내 스크린 샷으로 캡처 할 때까지 내 눈이라고 생각했습니다.

여기에 이미지 설명을 입력하십시오

왼쪽에있는 것은 내 게임에서 렌더링되는 것입니다. 오른쪽에있는 것은 원래 스프라이트입니다. (이것은 6 배 확대 된 Photoshop의 스크린 샷입니다.)

가장자리가 앨리어싱임을 알 수 있습니다. 서브 픽셀 렌더링과 거의 같습니다. 사실, 정수 값을 사용하여 스프라이트 (위치와 속도가 int 인)를 강제로 그리지 않으면 MonoGame이 부동 소수점 값으로 그리기를 맹세합니다. 그러나 그렇지 않습니다.

흐릿하게 나타나는 원인은 무엇입니까? 속도를 적용하지 않으면 발생하지 않습니다.

정확하게 말하면, 내 SpriteComponent수업에는 Vector2 Position필드가 있습니다. 전화하면 Draw기본적으로 new Vector2((int)Math.Round(this.Position.X), (int)Math.Round(this.Position.Y))위치를 사용 합니다.

고정 된 객체조차도 지터가 발생하기 전에 버그가있었습니다. 이는 직선 Position벡터를 사용 하고 값을 반올림하지 않기 때문 ints입니다. 둥근 대신에 Floor/ Ceiling를 사용 하면 스프라이트가 가라 앉거나 호버링되지만 (어느 쪽이든 한 픽셀 차이) 여전히 흐릿합니다.


1
이것이 적용되는 텍스처 필터링과 관련이있을 수 있습니까?
OriginalDaemon

셰이더 코드가 있습니까? 어떤 사람들은 픽셀을 중앙에 맞추기 위해 두 축에 반 픽셀을 추가합니다. 확실하지는 않지만 DirectX 전용이라고 생각합니다.
William Mariager

3
필터링 비활성화는 해결책이 아닌 해결 방법입니다.
Archy December

1
렌더링은 속도에 대해 아무것도 모르므로 SpriteBatch.Draw에 전달하는 위치, 크기 또는 기타 항목이 다르거 나 속도를 추가하기 전에 오류가 발생했습니다. SpriteBatch.Draw를 정확히 어떻게 호출합니까?
Archy December

1
@ ashes999이 호출을 디버그하고 this.X, this.Y 및 this.origin을 확인 했습니까? this.origin은 무엇으로 설정되어 있습니까? 이 Draw 호출이 동일 할 때 기본적으로 렌더링 결과가 다른 방법은 없습니다.
Archy December

답변:


3

이건 좀 ... 부끄러워.

정수 위치를 사용하지 않고 부동 위치를 사용 하는 것으로 나타났습니다 . Archy는 그의 의견으로 나를 올바른 길로 안내했습니다.@ashes999 did you debug this call and checked this.X, this.Y and this.origin?

추적 내역을 추가하자마자 아무 것도 추적되지 않는 것을 알았습니다. 내 SpriteComponent클래스는 정수 값을 올바르게 사용했지만 SpriteSheetComponent여전히 raw에서 float 값을 사용했습니다 Vector2 Position.

텍스처 필터링 및 클램핑을 시도하지는 않았지만 소스 이미지와 동일한 너비와 높이로 2D 이미지를 그리기 때문에 (스케일링 없음) 이것이 올바르게 변경되지 않았다는 의심이 들었습니다.


1
완료, 당신이 그것을 발견 기뻐요!
Archy December

2

XNA는 픽셀 중심을 위치로 사용하는 DirectX9를 사용합니다. 이는 Draw 클래스의 Vector2 기반 과부하를 사용할 때 두드러집니다. 빼기 (.5, .5)는 문제를 해결해야한다고 생각합니다.

자세한 정보는 여기에 있습니다.


int, int인수로 Vector2를 전달하기 때문에 기술적 으로이 작업을 수행 할 수 없습니다 . 게다가 움직이는 물체가 없으면 상황이 완벽하게 보입니다.
ashes999

물체가 움직이고 있다는 것은 무엇을 의미합니까? XNA는 모션에 대한 개념이 없으므로 사용자가 말한 곳을 그립니다. 일련의 고정 스냅 샷입니다. 어쨌든 사각형으로 반올림하므로 사각형 과부하를 사용해보십시오.
ClassicThunder

나만의 속도 구현이 있습니다. 속도에 따라 수레로 증가 SpriteComponent하는 Vector2위치를 가지고; 그릴 때, X와 Y Vector2의 정수 (둥근) 버전으로 새로운 것을 만듭니다 position. 속도가없는 고정 된 물체가 잘 보이기 때문에 이것은 문제가되지 않습니다.
ashes999

따라서 위치 벡터 p와 속도 벡터 v가 있다고 가정하면 p + = v와 같은 값을 더한 다음 둥근 값을 사용하여 p의 사본을 만듭니다. 그리고 이것은 드로우 콜이 동일 함에도 불구하고 이전의 p + = v와 동일한 위치를 가진 다른 값을 가져야합니까? 말이되지 않기 때문입니다.
ClassicThunder

그렇습니다. @Archy도 그렇게 말합니다. 디버깅하고 다시 확인하겠습니다. 나는 p += v동안 추가 Update하고로 렌더링합니다 new Vector2((int)Math.Round(p.X), (int)Math.Round(p.Y))).
ashes999

2

렌더링은 속도에 대해 아무것도 모르므로 SpriteBatch.Draw에 전달하는 위치, 크기 또는 기타 항목이 다르거 나 속도를 추가하기 전에 오류가 발생했습니다. SpriteBatch.Draw를 정확히 어떻게 호출합니까?

이 호출을 디버그하고 this.X, this.Y 및 this.origin을 확인 했습니까? this.origin은 무엇으로 설정되어 있습니까? 이 Draw 호출이 동일 할 때 기본적으로 속도의 렌더링 결과가 다른 방법은 없습니다.


1

텍스처 필터링이 켜져있을 수 있습니다. 그 의미를 잘 모를 경우 너비가 2 픽셀 인 이미지가있는 상황을 고려하십시오. 첫 번째 픽셀은 검은 색이고 두 번째 픽셀은 흰색입니다. 이 텍스처를 확대하면 텍스처 필터링이 켜져 있으면 흐리게 표시되고 검은 색과 흰색 픽셀 사이의 영역이 그라디언트 회색을 사용한다는 것을 알 수 있습니다.

필터링이 있거나없는 게임의 전형적인 예는 Doom이 필터링하지 않은 상태에서 필터링 한 Super Mario 64입니다.

속도를 사용하지 않으면 Sprite는 텍스처 중심이 XNA (또는 기본 API가 사용되는 모든 것)가 색상을 잡는 샘플 포인트에 놓이게됩니다. 플로트 속도로 이동하면 Sprite의 위치가 변경되어 샘플 포인트가 픽셀의 중심과 직접 정렬되지 않을 수 있으므로 최종 결과는 가장 가까운 픽셀의 평균 인 색상이 렌더링하는 데 사용됩니다.

Sprite를 화면에 실제로 크게 렌더링하여 필터링이 설정되어 있는지 확인할 수 있습니다. 흐릿하면 문제입니다.

렌더링에서 픽셀 단위의 정확도를 가져야하는 경우 어딘가에 저장된 위치에 대해 부동 소수점 값을 가지려고하지만 렌더링중인 객체의 위치에 정수 값을 사용하거나 필터링을 해제 할 수 있습니다 게임에 필요하지 않은 경우

당신은 또한 이것을 읽을 수 있습니다 .


내 질문에서 언급했듯이, 나는 전화 할 때 이미 내 위치에 정수를 사용하고 원래 이미지 크기를 사용하고 Draw있습니다. 따라서 어떻게 될 수 있는지 잘 모르겠습니다. 그러나 대규모 렌더링을 시도하고 텍스처 필터링을 해제하면 도움이되는지 확인합니다.
ashes999

1

SpriteBatch.Begin 호출에서 SamplerState를 SamplerState.PointClamp로 설정하십시오.

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