스프라이트 주위에 윤곽선을 그리는 효율적인 방법


21

저는 XNA를 사용하여 게임을 프로그래밍하고 있으며 스프라이트에 '선택된'효과를 얻기 위해 다양한 방법을 실험하고 있습니다. 내가 겪고있는 문제는 스프라이트 배치에 그려진 각 클릭 가능 항목이 단일 스프라이트 이상을 사용하여 그려지는 것입니다 (각 객체는 최대 6 개의 스프라이트로 구성 될 수 있음).

누군가가 X 픽셀 스프라이트에 윤곽선을 추가하는 방법에 대해 조언 할 수 있다면 고맙겠습니다 (윤곽선 너비는 다양한 수의 전체 픽셀이 될 수 있음).

미리 감사드립니다.

  • 그렉

답변:


20

이 작업을 수행하는 가장 쉬운 방법은 (실제로 성능에 묶여 있지 않는 한 가장 좋은 방법 일 것입니다) 스프라이트 사본 두 개를 갖는 것입니다.

  • 정규 버전
  • "컬러", 무채색 버전-기본적으로 스프라이트 X- 많은 픽셀의 흰색 버전이 원본보다 "더 희미합니다".

"지방"버전을 사용하여 전체 객체를 그린 다음 맨 위에 일반 버전을 그립니다.

"지방"버전을 흰색으로 만들면 SpriteBatch의 내장 색상 색조를 사용하여 선택 색상을 동적으로 변경할 수 있습니다.

"뚱뚱한"버전을 생성하려면 원본 스프라이트를 자동으로 가져와 알파 채널을 읽고 각 픽셀 주위의 원본 이미지에서 최대 알파 채널을 샘플링하여 새로운 알파 채널을 생성 하는 콘텐츠 파이프 라인 확장 프로그램 을 작성하는 것이 좋습니다 . RGB = (1,1,1) 설정.

스프라이트에 모두 윤곽선을 추가하기에 충분한 투명 테두리가 있는지 확인해야합니다 (컨텐츠 프로세서에서이를 확인할 수 있으며 필요한 경우 공간을 만들 수도 있음).

스프라이트가 거의없는 경우 좋은 이미지 편집기 (GIMP, Photoshop)를 사용하여 수동으로 수행 할 수 있습니다. 알파 채널 선택, 선택 확장, 알파 선택, 색상 채널 흰색 채우기.


4

각각의 오브젝트를 하나의 스프라이트에 먼저 그려야한다고 생각합니다. 그런 다음 스프라이트의 가장자리를 감지하여 가장자리를 찾을 때마다 픽셀을 그리는 쉐이더를 작성해야한다고 생각합니다. 이미 사용하고 있거나 포팅 할 수있는 셰이더가 이미 있어야합니다.


11
이런 종류의 쉐이더는 놀랍게도 성가시다. 나는 들었다. 고려해야 할 한 가지 사항은 (0, 255, 255, 0)과 같은 특정 색상으로 스프라이트 텍스처에 윤곽선을 직접 인코딩하고 스프라이트를 선택할 때 셰이더가 해당 색상을 변환하도록하는 것입니다. 그런 다음 셰이더는 사소한 색상 변경이며 개요 및 원하는 세부 사항을 높은 수준의 아티스트가 제어 할 수 있습니다.

4

요구 사항에 따라 스프라이트에 대한 주문형 개요를 만드는 것이 효과적 일 수도 있습니다. 나는 스프라이트가 투명성을 가지고 있고 직사각형이 아닌 불규칙한 모양이라고 가정합니다 (이것은 잘 작동하지만 개요 직사각형은 사소해야합니다).

when selected:
   outline = new sprite canvas of appropriate size
   for sprite in object:
      # use larger numbers for thicker outlines
      for x in (-1, 0, 1) and y in (-1, 0, 1):
         render sprite mask into canvas at x,y with desired color

매번 그릴 때마다이 작업을 수행 할 필요는 없지만 스프라이트를 전환 할 때 새 윤곽선 스프라이트를 만들면됩니다.


예, 이것이 제가 제안하고 싶었던 것입니다. 마스크 된 스프라이트를 기존 스프라이트 아래에서 원래 스프라이트의 왼쪽, 오른쪽, 위쪽 및 아래쪽으로 1 픽셀 렌더링합니다. 많은 게임에서이 방법을 사용하여 렌더링 된 텍스트의 윤곽을 그리거나 4 개의 위치 중 2 개만으로 그림자를 만듭니다.
Kaj

1

가장 간단한 무차별 접근 방식은 각 스프라이트의 사본 두 개 (일반 및 강조 표시)를 만드는 것입니다. 그런 다음 강조 표시되면 바꾸십시오.

여분의 메모리가 있다면 더 복잡 할 필요가 없습니다. 또한 아티스트는 강조 표시 될 때 모양을 완벽하게 제어 할 수 있으므로 개요 또는 원하는 다른 작업을 수행 할 수 있습니다.


문제의 일부는 OP가 각 객체를 여러 스프라이트로 만들 수 있다고 말합니다. 따라서 윤곽선은 각 구성 요소 스프라이트 주위에 별도의 윤곽선이 아닌 결합 된 객체의 윤곽선이어야한다고 생각합니다.
Chris Howe

1
Chris, 결합 된 오브젝트의 윤곽 일 필요는 없으며 여러 스프라이트로 만들어진 오브젝트에 적합합니다. wkerslake가 말한대로 정확하게 수행하되 강조 표시된 스프라이트를 해당 오브젝트의 모든 일반 스프라이트 뒤에 그립니다. 이렇게하면 오브젝트가 얼마나 많은 스프라이트로 구성 되더라도 하이라이트는 해당 오브젝트에 대한 그리기 시간의 두 배 이상을 약간만 사용합니다. 이는 결합 된 스프라이트로 렌더링시 윤곽선을 생성하는 것보다 훨씬 적어야합니다.
AttackingHobo

1

각 스프라이트마다 기본 스프라이트의 개요 인 다른 스프라이트도 있습니다. 윤곽선 개체를 그릴 때 기본 스프라이트를 그린 다음 결합 렌더링의 마스크를 만든 다음 마스크를 제외한 윤곽 스프라이트를 그립니다.


2
윤곽선 스프라이트를 먼저 그려서 그 위에 일반 스프라이트를 그리지 않겠습니까?
Chris Howe

이것을하지 않는 한 가지 이유 (또는 Chris의 제안)는 텍스처 메모리의 두 배를 사용하기 때문입니다. 또 다른 이유는 스프라이트를 변경할 때마다 두 개의 파일을 업데이트해야하기 때문에 아티스트 워크 플로가 중단되기 때문입니다.

2
글쎄, 당신은 이상적으로 두 개의 실제 스프라이트 자산이 없을 것입니다. 스프라이트에 알파 테스트를 사용하는 경우 개요를 스프라이트에 넣고 투명 영역보다 약간 높은 알파를 줄 수 있습니다. 그런 다음 알파 테스트 참조 값을 제어하여 윤곽선의 표시 여부를 제어 할 수 있습니다. 내가 말하고 싶은 것은 스프라이트의 2 가지 버전 (2 개의 자산이든 2 개의 같은 자산이든)이든 먼저 개요 버전을 그린 다음 일반 버전을 그려야한다는 것입니다. 이런 식으로 멋진 쉐이더, 마스크 등이 필요하지 않습니다.
Chris Howe

1
Chris의 아이디어는 장점이 있습니다. 또한 자산 / 컨텐츠 파이프 라인의 일부로 실행되는 개요 스프라이트의 알파를 생성하는 도구를 생성하는 경우 아티스트가 2 개의 파일 (또는 동일한 자산)을 업데이트하지 않아도됩니다. 텍스처 메모리는 문제가 될 수도 있고 아닐 수도 있지만 별도의 개요 스프라이트는 DXT 압축이 가능해야합니다. 비디오 메모리의 원본 텍스처 크기의 1/6이며 충실도 손실이 없습니다.
jpaver

1

다른 장단점이있는 몇 가지 솔루션.

가장 쉬운 방법 : 평면 색상을 여러 번 사용하여 객체를 렌더링하고 위치 (왼쪽, 위, 아래, 오른쪽 등 오프셋)를 흔들면 그 위에 렌더링 한 모든 버전의 개요 버전이 생성되지만 성능 비용이 발생하지는 않습니다. 추가 렌더링을 많이하지 않고도 굵은 테두리를 만들 수 있습니다. 하나 또는 두 개의 픽셀 테두리는 4x로 괜찮을 수 있습니다.

가장 빠름 : 텍스처를 사전 처리하고 이미 테두리가 있거나 복사본이거나 복사본이거나 음영이있는 회색조 8 비트 마스크입니다. 이것은 메모리 비용으로 빠를 것입니다.

최선 : 내 의견이지만 객체의 부호있는 거리 필드 (SDF) 표현을 생성하는 것이 가장 좋은 해결책 일 것입니다. 이 텍스처는 소스 텍스처보다 훨씬 작을 수 있으며 여전히 유용한 데이터를 캡처합니다. 기본적으로 각 픽셀은 픽셀을 생성하는 데 사용 된 객체에서 얼마나 멀리 떨어져 있는지 인코딩합니다. 이 데이터를 활용하면 광선에서 윤곽선까지 모든 종류의 효과를 쓸 수 있습니다. 테두리의 크기와 색상 등이 변경 될 수 있으며 여전히 비교적 저렴한 셰이더이며 하나의 추가 추첨입니다. 단점은 툴링 및 전처리입니다.


0

효율성은 확실하지 않지만 가장 쉽게 볼 수있는 방법은 먼저 선택한 색상으로 더 큰 버전의 스프라이트를 그리는 것입니다. 그 위에 스프라이트를 그립니다. 첫 번째 스프라이트의 가장자리 만 보이므로 선택 효과가 나타납니다.

편집 : 그러나 주석에서 볼 수 있듯이 이것은 좋은 생각이 아닙니다.


1
스프라이트를 확장하는 것만으로는 실제적인 윤곽이 나오지 않습니다
Iain

2
나는 그렇게 생각하지 않지만 쉽지 않을 것입니다.
공산주의 오리

2
많은 것들이 쉽지만 문제를 해결하지는 못합니다. 흥미로운 실루엣을 가진 스프라이트의 경우 스케일 업은 절대 가비지를 생성합니다.

스케일 업은 단색 사각형 또는 원형 오브젝트에만 적합합니다. 모양이 실제로 넓거나 키가 크거나 틈이 있으면 정말 나빠 보일 것입니다.
AttackingHobo

3
스케일 업은 아무것도하지 않는 것보다 더 나은 결과를 제공 할뿐만 아니라 "완벽한"경로로 나아가는 유용한 단계 일 것입니다. 그래픽 결과는 완벽하지는 않지만 내부 도구를위한 것이면 충분합니다.
dash-tom-bang

0

스프라이트 확장에 동의합니다. 지금까지 가장 쉬운 경로이며, 특히이 목적을 위해 추가 스프라이트를 만들지 않고도 모든 스프라이트를 선택하는 데 적용 할 수 있습니다.

  • 즉, spriteOutline.Scale = spriteOriginal.Scale * 0.1f; spriteOutline.Color = 새 색 (255, 0, 0, 255);

0

원래 스프라이트의 색상을 윤곽선 색상으로 바꾸거나 원하는 경우 색조를 적용하십시오. x, y = (-1, -1), (+ 1, -1), (-1, + 1), (+1)에서 1 픽셀 오프셋으로이 음영 처리 또는 색조 스프라이트를 4 번 렌더링합니다. , +1). 오브젝트를 구성하는 모든 스프라이트에 대해 반복하십시오.

그런 다음 원래 스프라이트를 (0,0)에 올바른 순서로 렌더링하십시오.

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