서브 픽셀 단위로 스프라이트를 어떻게 이동합니까?


11

픽셀이 켜져 있거나 꺼져 있습니다. 스프라이트를 이동할 수있는 최소량은 단일 픽셀입니다. 그러면 스프라이트가 프레임 당 1 픽셀보다 느리게 움직이는 방법은 무엇입니까?

내가 한 방법은 변수에 속도를 추가하고 변수가 1 (또는 -1)에 도달했는지 테스트하는 것이 었습니다. 그렇다면 스프라이트를 이동하고 변수를 0으로 재설정합니다.

update(dt):
    temp_dx += speed * dt
    temp_dy += speed * dt

    if (temp_dx > 1)
        move sprite
        reset temp_dx to 0
    if (tempy_dy > 1)
        move sprite
        reset temp_dy to 0

나는 어리석게 느끼고 스프라이트의 움직임이 매우 육안으로 보이기 때문에이 접근법을 싫어했습니다. 그렇다면 어떤 방식으로 하위 픽셀 이동을 구현 하시겠습니까?


당신이 할 수있는 유일한 것은 이중 선형 필터링입니다.
AturSams

프레임 당 1 픽셀 미만으로 이동하는 경우 어떻게 변칙적으로 보일 수 있습니까?

답변:


17

여러 가지 옵션이 있습니다.

  1. 당신이하는대로하십시오. 당신은 이미 그것이 부드럽게 보이지 않는다고 말했습니다. 그러나 현재 방법에는 몇 가지 결함이 있습니다. 의 경우 x다음을 사용할 수 있습니다.

    tempx += speed * dt
    
    while (tempx > 0.5)
      move sprite to x+1
      tempx -= 1
    while (tempx < -0.5)
      move sprite to x-1
      tempx += 1

    이것은 더 좋을 것입니다. 0.5를 통과하면 이전보다 다음 값에 더 가깝기 때문에 if 문에서 0.5를 사용하도록 전환했습니다. 나는 시간 단계 당 1 픽셀 이상의 움직임을 허용하기 위해 while 루프를 사용했습니다 (가장 좋은 방법은 아니지만 작고 읽기 쉬운 코드를 만듭니다). 천천히 움직이는 객체의 경우 픽셀 정렬의 근본적인 문제를 다루지 않았기 때문에 여전히 삐걱 거리지 않습니다.

  2. 스프라이트에 여러 그래픽이 있고 서브 픽셀 오프셋에 따라 다른 그래픽을 사용하십시오. 단지 X에 부드럽게 서브 픽셀을하려면, 예를 들어, 당신은 당신의 스프라이트를위한 그래픽을 만들 수 x+0.5및 위치 사이 인 경우 x+0.25x+0.75, 원본 대신이 스프라이트를 사용합니다. 더 나은 위치 지정을 원하면 더 많은 서브 픽셀 그래픽을 만드십시오. 당신이 이렇게 할 경우 xy렌더링의 전화 번호 신속 풍선 할 간격 수의 제곱과 숫자 저울로, :의 간격이 0.54 렌더링을 필요로, 0.2516을 필요로한다.

  3. 수퍼 샘플. 이는 서브 픽셀 해상도로 이미지를 생성하는 게으른 (그리고 잠재적으로 매우 비싼) 방법입니다. 기본적으로 장면을 렌더링하는 해상도를 두 배 (또는 그 이상)로 설정 한 다음 런타임에 축소합니다. 성능이 빠르게 저하 될 수 있으므로 여기서주의하십시오. 덜 공격적인 방법은 스프라이트를 수퍼 샘플링하고 런타임에 다운 스케일하는 것입니다.

  4. Zehelvion 에서 제안한대로 사용중인 플랫폼에서 이미이를 지원할 수 있습니다. 정수가 아닌 x 및 y 좌표를 지정할 수있는 경우 텍스처 필터링을 변경하는 옵션이있을 수 있습니다. 가장 가까운 이웃이 종종 기본값이며, 이로 인해 "고르지 않은"움직임이 발생합니다. 다른 필터링 (선형 / 입방체)은 훨씬 더 부드러운 효과를 가져옵니다.

2. 3.와 4. 사이의 선택은 그래픽이 어떻게 구현되는지에 달려 있습니다. 비트 맵 스타일의 그래픽은 사전 렌더링에 훨씬 적합하지만 벡터 스타일은 스프라이트 수퍼 샘플링에 적합 할 수 있습니다. 당신의 시스템이 그것을 지원한다면, 4. 좋은 방법 일 것입니다.


opt 1에서 임계 값을 0.5로 바꾸는 이유는 무엇입니까? 또한 왜 문을 while 루프로 옮겼는지 알 수 없습니다. 업데이트 기능은 틱당 한 번 호출됩니다.
bzzr

1
좋은 질문-귀하의 의견에 따라 답변을 명확하게했습니다.
Jez

수퍼 샘플링은 "게으른"것일 수 있지만, 특히 렌더링의 다른 측면을 단순화 할 수있는 경우 2x 또는 4x 오버 샘플링의 성능 비용은 특별한 문제가되지 않습니다.
supercat

예산이 큰 게임에서는 일반적으로 그래픽 설정에 앤티 앨리어싱 옵션으로 3이 표시됩니다.
케빈

1
@ 케빈 : 당신은 실제로하지 않을 것입니다. 대부분의 게임 은 약간 다른 멀티 샘플링을 사용 합니다. 예를 들어 깊이 범위 샘플뿐만 아니라 커버리지가 다른 다른 변형도 일반적으로 사용됩니다. 수퍼 샘플링은 프래그먼트 셰이더 실행 비용으로 인해 거의 수행되지 않습니다.
imallett

14

많은 오래된 skool 게임 이이 문제를 해결 (또는 숨기) 한 가지 방법은 스프라이트를 애니메이션하는 것이 었습니다.

즉, 스프라이트가 프레임 당 1 픽셀 미만으로 이동하려는 경우 (또는 특히 픽셀 / 프레임 비율이 3 프레임의 2 픽셀과 같이 이상한 경우) n 을 만들어서 위선 감을 숨길 수 있습니다. 그 n 프레임에 걸쳐 스프라이트를 k < n 픽셀 만큼 움직 인 프레임 애니메이션 루프 .

요점은 스프라이트가 항상 각 프레임 에서 어떤 식 으로든 움직이는 한 전체 스프라이트가 갑자기 "앞으로 튀어 나오는"단일 프레임이 없을 것이라는 점입니다.


나는 (내가에서 애니메이션 파고의 몇 가지 예라고 생각하지만,이 문제를 설명하기 위해 오래된 비디오 게임에서 실제 스프라이트를 찾을 수 없습니다 레밍은 그렇게했다)를,하지만 밝혀 "글라이더" 에서 패턴 생명의 콘웨이의 게임 한다 아주 좋은 그림 :

여기에 이미지 설명을 입력하십시오
CC-By-SA 3.0 라이센스에 따라 Kieff / Wikimedia Commons에 의한 애니메이션 .

여기에서 크롤링하는 작은 검은 색 픽셀 블록이 오른쪽 아래로 이동합니다. 주의 깊게 살펴보면 대각선으로 한 픽셀 씩 크롤링하기 위해 4 개의 애니메이션 프레임이 필요하지만 각 프레임 에서 어떤 방식 으로든 움직이므로 움직임이 이상하게 보이지 않습니다 (최소한 더 이상 어쨌든 그 프레임 속도를 보는 것보다 육포).


2
속도가 고정되어 있거나 프레임 당 1/2 픽셀 미만이거나 애니메이션이 모션의 변화를 모호하게 할만큼 충분히 크고 빠르면이 방법이 좋습니다.
supercat

카메라가 스프라이트를 따라야하는 경우에도 매끄럽게 움직이지 않기 때문에 여전히 문제가 발생할 수 있습니다.
Elden Abob

6

스프라이트의 위치는 부동 소수점 수량으로 유지되어야하며 표시 직전에 정수로 반올림되어야합니다.

스프라이트를 최고 해상도로 유지하고 표시하기 전에 스프라이트를 다운 샘플링 할 수도 있습니다. 스프라이트를 3 배 디스플레이 해상도로 유지 한 경우 스프라이트의 서브 픽셀 위치에 따라 9 개의 다른 실제 스프라이트가 있습니다.


3

여기서 유일한 해결책은 이중 선형 필터링을 사용하는 것입니다. 아이디어는 GPU가 겹치는 4 개의 스프라이트 픽셀을 기반으로 각 픽셀의 값을 계산하도록하는 것입니다. 일반적이고 효과적인 기술입니다. 스프라이트를 텍스처로 2d- 플레인 (빌보드)에 놓기 만하면됩니다. 그런 다음 GPU를 사용하여이 평원을 렌더링하십시오. 이것은 잘 작동하지만 결과가 다소 흐려지고 목표로하는 경우 8 비트 또는 16 비트 모양을 잃을 것으로 예상됩니다.

찬성 :

이미 매우 빠른 하드웨어 기반 솔루션을 구현했습니다.

단점 :

8 비트 / 16 비트 충실도 손실


1

부동 소수점은이를 수행하는 일반적인 방법입니다. 특히 부동 좌표가있는 음영 처리 된 다각형으로 하드웨어가 만족스러운 GL 대상에 렌더링하는 경우 특히 그렇습니다.

그러나 현재하고있는 일을 수행하는 또 다른 방법이 있지만 약간 덜 간단합니다 : 고정 소수점. 32 비트 위치 값은 화면의 축을 따라 거의 확실히 4k 픽셀 미만이지만 0에서 4,294,967,295까지의 값을 나타낼 수 있습니다. 따라서 고정 된 "이진 점"(소수점과 유사하게)을 중간에 놓고 다른 16 비트의 서브 픽셀 해상도로 0-65536의 픽셀 위치를 나타낼 수 있습니다. 그런 다음 평소와 같이 숫자를 추가 할 수 있습니다. 화면 공간으로 변환 할 때마다 또는 두 숫자를 곱할 때마다 16 비트를 오른쪽으로 이동하여 변환해야한다는 것을 기억해야합니다.

(플로팅 포인트 단위가없는 Intel 386을 사용하던 당시에는 16 비트 고정 소수점으로 3D 엔진을 작성했습니다. 프레임 당 200 Phong 음영 다각형의 블라인드 속도를 달성했습니다.)


1

여기에 다른 답변 외에도 디더링을 어느 정도 사용할 수 있습니다. 디더링은 물체의 픽셀 가장자리가 배경과 일치하도록 밝거나 어두워지는 곳으로 가장자리가 더 부드럽습니다. 예를 들어 4 픽셀 정사각형을 가지고 있다고 가정 해 보겠습니다.

OO
OO

이 1/2 픽셀을 오른쪽으로 움직이면 아무것도 움직이지 않습니다. 그러나 약간의 디더링으로 약간의 움직임의 환상을 만들 수 있습니다. O를 검정으로, o를 회색으로 고려하면 다음과 같이 할 수 있습니다.

oOo
oOo

한 프레임에서

 OO
 OO

다음에. 회색 가장자리가있는 실제 "정사각형"은 실제로 3 픽셀을 차지하지만 검정보다 밝은 회색이기 때문에 더 작아 보입니다. 그러나 이것은 코딩하기가 어려울 수 있으며 지금은이 작업을 수행하는 것을 실제로 알지 못합니다. 사물에 디더링을 사용하기 시작한 시간에 대해 해상도가 빠르게 향상되었으며 이미지 조작과 같은 것을 제외하고는 많이 필요하지 않았습니다.

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