원활한 타일 맵 렌더링 (테두리없는 인접 이미지)


18

타일셋 이미지에서 타일을 그려 타일 맵을 그리는 2D 게임 엔진이 있습니다. OpenGL은 기본적으로 전체 텍스처 ( GL_REPEAT) 만 래핑 할 수 있고 그 일부만 래핑 할 수 없으므로 각 타일은 별도의 텍스처로 분리됩니다. 그런 다음 동일한 타일의 영역이 서로 인접하게 렌더링됩니다. 의도 한대로 작동 할 때의 모습은 다음과 같습니다.

이음새가없는 타일 맵

그러나 분수 스케일링을 도입하자마자 이음새가 나타납니다.

솔기가있는 타일 맵

왜 이런 일이 발생합니까? 쿼드의 경계를 블렌딩하는 선형 필터링 때문이라고 생각했지만 여전히 포인트 필터링으로 발생합니다. 내가 지금까지 찾은 유일한 해결책은 모든 위치를 확인하는 것입니다 만 스케일링 정수 값에서 발생, 사용 포인트 필터링. 이로 인해 게임의 시각적 품질이 저하 될 수 있습니다 (특히 서브 픽셀 위치 지정이 더 이상 작동하지 않아 모션이 매끄럽지 않음).

내가 시도 / 고려한 것들 :

  • 앤티 앨리어싱은 이음새를 줄이지 만 완전히 제거하지는 않습니다.
  • 밉 매핑을 끄면 효과가 없습니다.
  • 각 타일을 개별적으로 렌더링하고 가장자리를 1px만큼 돌출시킵니다.하지만 더 이상 타일 영역을 한 번에 렌더링 할 수 없으며 투명 영역의 가장자리를 따라 다른 인공물을 생성하기 때문에 최적화 해제입니다
  • 소스 이미지 주위에 1px 테두리를 추가하고 마지막 픽셀을 반복하지만 더 이상 2의 제곱이 아니므로 NPOT를 지원하지 않는 시스템과의 호환성 문제가 발생합니다
  • 바둑판 식 이미지를 처리하기 위해 커스텀 셰이더를 작성하지만 어떻게 다르게 할 것입니까? GL_REPEAT경계에서 이미지의 반대쪽에서 픽셀을 잡고 투명도를 선택하지 않아야합니다.
  • 형상이 정확히 인접 해 있고 부동 소수점 반올림 오류가 없습니다.
  • 프래그먼트 셰이더가 동일한 색상을 반환하도록 하드 코딩 된 경우 이음새가 사라집니다 .
  • 텍스처로 설정하는 경우 GL_CLAMP대신에 GL_REPEAT, 이음매가 없어 (렌더링 잘못 있지만).
  • 텍스처로 설정하는 경우 GL_MIRRORED_REPEAT, 솔기가 사라 (렌더링 다시 잘못된 있지만).
  • 배경을 빨간색으로 만들면 이음새가 여전히 흰색입니다. 이것은 투명도가 아닌 어딘가에서 불투명 한 흰색을 샘플링하고 있음을 나타냅니다.

따라서 이음새 GL_REPEAT가 설정된 경우에만 나타납니다 . 어떤 이유로이 모드에서만 지오메트리의 가장자리에 약간의 블리드 / 누설 / 투명성이 있습니다. 어떻게 그렇게 될수 있니? 전체 텍스처가 불투명합니다.


텍스처 샘플러를 클램핑하도록 설정하거나 테두리 색상을 조정 해보십시오. 또한 GL_Repeat은 단순히 UV 좌표를 감싸므로 텍스처의 일부가 아닌 전체 텍스처 만 반복한다고 말할 때 개인적으로 약간 혼란 스럽습니다.
Evan

1
어떻게 든 메쉬에 균열이 생길 수 있습니까? 텍스처를 샘플링하는 대신 단색을 반환하도록 셰이더를 설정하여 테스트 할 수 있습니다. 이 시점에서 여전히 균열이 보이면 지오메트리에있는 것입니다. 앤티 앨리어싱이 이음새를 줄인다는 사실은 앤티 앨리어싱이 텍스처 샘플링에 영향을 미치지 않기 때문에 이것이 문제가 될 수 있음을 시사합니다.
Nathan Reed

텍스처 아틀라스에서 개별 타일의 반복을 구현할 수 있습니다. 그래도 추가 텍스처 좌표 수학을 수행하고 각 타일 주위에 테두리 텍셀을 삽입해야합니다. 이 기사 는 이것을 많이 설명합니다 (주로 D3D9의 성가신 텍스처 좌표 규칙에 중점을 둡니다). 또는 구현이 충분히 새롭다면 타일 맵에 배열 텍스처를 사용할 수 있습니다. 각 타일의 크기가 동일하다고 가정하면 큰 효과가 있으며 추가 좌표 계산이 필요하지 않습니다.
Andon M. Coleman

좌표 방향으로 GL_NEAREST샘플링 된 3D 텍스처 는이 시나리오에서 대부분의 것의 R배열 텍스처와 마찬가지로 작동 합니다. 밉 매핑은 작동하지 않지만 응용 프로그램으로 판단하면 밉맵이 필요하지 않을 수 있습니다.
Andon M. Coleman

1
CLAMP로 설정하면 렌더링이 "잘못된"방법은 무엇입니까?
Martijn Courteaux

답변:


1

이음새는 GL_REPEAT로 샘플링 할 때 올바른 동작입니다. 다음 타일을 고려하십시오.

테두리 타일

분수 값을 사용하여 타일 가장자리에서 샘플링하면 가장자리와 반대 가장자리의 색상이 혼합되어 잘못된 색상이 나타납니다. 왼쪽 가장자리는 녹색이어야하지만 녹색과 베이지 색의 혼합입니다. 오른쪽 가장자리는 베이지 색이어야하지만 혼합 색상입니다. 특히 녹색 배경의 베이지 색 선이 눈에 잘 띄지 만 자세히 보면 가장자리에 녹색 출혈이 생길 수 있습니다.

스케일 타일

앤티 앨리어싱은 이음새를 줄이지 만 완전히 제거하지는 않습니다.

MSAA는 다각형 가장자리 주위에 더 많은 샘플을 가져 와서 작동합니다. 가장자리의 왼쪽 또는 오른쪽으로 채취 한 샘플은 "녹색"(다시 첫 번째 사진의 왼쪽 가장자리를 고려하여)이되고, "베이지"영역에서 부분적으로 샘플링하면 한 샘플 만 가장자리에 "채색"됩니다. 샘플이 혼합되면 효과가 줄어 듭니다.

가능한 해결책:

어쨌든GL_CLAMP 질감의 반대쪽에있는 픽셀에서 번짐이 생기지 않도록로 전환해야합니다 . 그런 다음 세 가지 옵션이 있습니다.

  1. 앤티 앨리어싱을 활성화하여 타일 간 전환을 약간 매끄럽게합니다.

  2. 텍스처 필터링을로 설정하십시오 GL_NEAREST. 이렇게하면 모든 픽셀에 단단한 가장자리가 생겨 다각형 / 스프라이트 가장자리를 구분할 수 없게되지만 게임의 스타일이 약간 변경됩니다.

  3. 이미 논의 된 1px 테두리를 추가하고 테두리에 인접한 타일의 색상이 있는지 확인하십시오 (반대 가장자리의 색상이 아님).

    • 텍스처 아틀라스로 전환하기에 좋은시기 일 수도 있습니다 (NPOT 지원에 대해 염려 할 경우 더 크게 만드십시오).
    • 이것은 GL_LINEAR폴리곤 / 스프라이트의 가장자리에서 유사한 필터링을 가능하게하는 유일한 "완벽한"솔루션 입니다.

고마워-텍스처를 감싸는 것이 그것을 설명합니다. 나는 그 해결책을 살펴볼 것이다!
AshleysBrain

6

OpenGL은 기본적으로 전체 텍스처 (GL_REPEAT) 만 랩핑 할 수 있고 그 일부만이 아니라 각 타일이 별도의 텍스처로 분리됩니다. 그런 다음 동일한 타일의 영역이 서로 인접하게 렌더링됩니다.

OpenGL에서 하나의 일반 텍스처 쿼드를 표시하는 것을 고려하십시오. 규모에 상관없이 이음새가 있습니까? 아뇨. 목표는 모든 장면 타일을 단일 텍스처에 단단히 포장 한 다음 화면에 보내는 것입니다. 편집 더 자세히 설명하려면 : 각 타일 쿼드에 불연속 경계 정점 있는 경우 대부분의 상황에서 겉보기에 이음새가없는 것처럼 보입니다. GPU 하드웨어 작동 방식 ... 부동 소수점 오류는 현재 관점을 기반으로 이러한 간격을 생성합니다 ... 두 개의면이 동일한 매니 폴드 내에 인접 해 있기 때문에 통합 매니 폴드에서 방지되는 오류(서브 메쉬) 하드웨어는 이음새없이 렌더링합니다. 당신은 수많은 게임과 앱에서 이것을 보았습니다. 이 문제를 한 번에 방지하려면 꼭짓점을 두 배로 늘리지 않고 단일 서브 메쉬에 단단히 포장 된 하나의 텍스처가 있어야합니다. 이 사이트와 다른 곳에서 몇 번이고 발생하는 문제입니다. 타일의 꼭지점을 병합하지 않으면 (4 개의 타일이 모두 꼭지점을 공유 함) 이음새가 필요합니다.

(전체지도의 네 모퉁이를 제외하고는 꼭짓점이 필요하지 않을 수도 있습니다. 음영에 대한 접근 방식에 따라 다릅니다.)

해결 방법 : 모든 타일 텍스처 간격없이 FBO / RBO로 렌더링 (1 : 1) 한 다음 해당 FBO를 기본 프레임 버퍼 (화면)로 보냅니다. FBO 자체는 기본적으로 단일 텍스처이므로 스케일링에 공백이 생길 수 없습니다. GL_LINEAR ...을 사용하면 화면 픽셀 경계에 속하지 않는 모든 텍셀 경계가 혼합됩니다. 정확히 원하는 것입니다. 이것이 표준 접근법입니다.

또한 스케일링에 대한 여러 가지 경로가 열립니다.

  • FBO를 렌더링 할 쿼드의 크기 조정
  • 해당 쿼드의 UV 변경
  • 카메라 설정을 다루다

나는 이것이 우리에게 잘 작동한다고 생각하지 않습니다. 10 % 줌에서 10 배 더 큰 영역을 렌더링한다고 제안하는 것 같습니다. 충전 속도가 제한된 장치에는 적합하지 않습니다. 또한 GL_REPEAT가 왜 이음새 만 유발하고 다른 모드는 사용하지 않는 이유에 대해서는 여전히 미스터리입니다. 어떻게 그럴 수 있니?
AshleysBrain

@AshleysBrain 비 조작. 나는 당신의 진술에 의해 신비 합니다. 확대 / 축소를 10 % 늘리면 유효 노출 률이 10 배 증가하는 방법을 설명해주세요. 또는 뷰포트 클리핑으로 단일 패스에서 100 % 이상의 채우기 속도를 방지 할 수 있기 때문에 줌이 10 배 증가하는 방법은 무엇입니까? 일반적인 기술인 RTT를 사용하여 최종 출력을 통합하여 효율적이고 완벽한 방식으로 이미 의도 한 것을 정확하게 표시하는 것이 좋습니다 . 하드웨어는 뷰포트 클리핑, 스케일링, 블렌딩 및 보간을 2D 엔진 일 뿐이므로 거의 무료로 처리합니다.
엔지니어

@AshleysBrain 현재 접근 방식의 문제를 명확하게하기 위해 내 질문을 편집했습니다.
엔지니어

@ArcaneEngineer 안녕하세요, 솔기 문제를 완벽하게 해결하는 귀하의 접근 방식을 시도했습니다. 그러나 이제는 이음새가 아닌 픽셀 오류가 있습니다. 내가 여기서 언급 한 문제에 대해 알 수 있습니다 . 이 원인이 무엇인지 알 수 있습니까? WebGL에서 모든 작업을 수행하고 있습니다.
Nemikolh

1
@ArcaneEngineer 여기에 설명이 너무 번거 롭다는 새로운 질문을하겠습니다. 불편을 드려 죄송합니다.
Nemikolh

1

이미지가 하나의 표면으로 나타나야하는 경우 3D 메쉬 / 평면에서 하나의 표면 질감 (스케일 1x)으로 렌더링합니다. 각각을 별도의 3D 객체로 렌더링하면 반올림 오류로 인해 항상 이음새가 생깁니다.

@ Nick-Wiggill의 대답은 정확합니다. 오해했다고 생각합니다.


0

시도해 볼만한 두 가지 가능성 :

  1. 텍스처 필터링 GL_NEAREST대신 사용하십시오 GL_LINEAR. (Andon M. Coleman이 지적한대로)

    GL_LINEAR(실제로) 이미지를 너무 흐리게하여 (가장 가까운 픽셀 사이를 보간) 한 픽셀에서 다음 픽셀로 부드럽게 색상을 전환 할 수 있습니다. 이렇게하면 텍스처가 고르지 않은 픽셀을 갖지 못하기 때문에 텍스처를 더 잘 보이게 만들 수 있습니다. 또한 한 타일의 한 픽셀에서 약간의 갈색이 인접한 타일의 인접한 녹색 픽셀로 흐려질 수 있습니다.

    GL_NEAREST가장 가까운 픽셀을 찾아 해당 색상을 사용합니다. 보간이 없습니다. 결과적으로 실제로 약간 빠릅니다.

  2. 각 타일의 텍스처 좌표를 약간 줄입니다.

    이미지에서 타일을 확장하는 대신 소프트웨어에서 타일을 축소하는 것을 제외하고 각 타일 주위에 여분의 픽셀을 버퍼로 추가하는 것과 같습니다. 16x16px 타일 대신 렌더링하는 동안 14x14px 타일.

    너무 많은 갈색을 섞지 않고 14.5x14.5 타일로 도망 갈 수도 있습니다.

--편집하다--

옵션 # 2의 설명 시각화

위의 이미지에서 볼 수 있듯이 여전히 두 텍스처의 힘을 쉽게 사용할 수 있습니다. 따라서 NPOT 텍스처를 지원하지 않는 하드웨어를 지원할 수 있습니다. 에서 (0.0f, 0.0f)로 가는 대신에 텍스처 좌표가 변경되는 것은에서 로 (1.0f, 1.0f)이동하는 (0.03125f, 0.03125f)(0.96875f, 0.96875f)입니다.

이렇게하면 텍스 좌표가 타일 안에 약간 들어가게되어 게임에서 효과적인 해상도를 떨어 뜨립니다 (하드웨어가 아니더라도 여전히 2의 텍스쳐를 갖지만).


GL_NEAREST (일명 포인트 필터링)를 시도했지만 문제가 해결되지 않았다고 언급했습니다. NPOT 장치를 지원해야하기 때문에 # 2를 할 수 없습니다.
AshleysBrain 17 년

몇 가지 사항을 정리할 수있는 수정을했습니다. (나는 "NPOT [(2의 비 전력)] 장치를 지원해야한다"는 것은 2의 힘으로 텍스처를 유지하는 데 필요한 라인을 따라 무언가를 의미하는 것으로 가정하고있다.)
Wolfgang Skyler

0

다음은 제가 생각할 수있는 일입니다. 두 개의 타일이 충돌하는 경우 가장자리의 x 구성 요소가 같아야합니다. 이것이 사실이 아니면 반대 방향으로 반올림 될 수 있습니다. 따라서 x 값이 정확히 같은지 확인하십시오. 어떻게 이런 일이 발생하는지 확인합니까? 예를 들어 10을 곱한 다음 반올림 한 다음 10으로 나눕니다 (정점이 정점 셰이더로 들어가기 전에 CPU에서만 수행). 올바른 결과를 제공해야합니다. 또한 변환 행렬을 사용하여 타일별로 타일을 그리지 않고 배치 VBO에 배치하여 행렬 곱셈과 함께 손실 IEEE 부동 소수점 시스템에서 잘못된 결과가 나오지 않도록합니다.

왜 이것을 제안합니까? 내 경험상, 꼭짓점이 정점 셰이더에서 나올 때 정확히 동일한 좌표를 가지면 해당 삼각형을 채우면 완벽한 결과를 얻을 수 있습니다. 수학적으로 올바른 것은 IEEE로 인해 약간 벗어날 수 있습니다. 숫자를 더 많이 계산할수록 결과의 정확도가 떨어집니다. 그렇습니다. 매트릭스 곱셈에는 상당히 많은 연산이 필요합니다. VBO를 만들 때 곱셈과 덧셈으로 만 수행 할 수 있으므로보다 정확한 결과를 얻을 수 있습니다.

문제는 스프라이트 시트 (아틀라스라고도 함)를 사용하고 있고 텍스처를 샘플링 할 때 인접한 타일 텍스처의 픽셀이 선택된다는 것입니다. 이것이 일어나지 않도록하려면 UV 매핑에서 작은 테두리를 만드는 것입니다. 따라서 64x64 타일을 사용하는 경우 UV 매핑이 약간 줄어 듭니다. 얼마예요? 내 게임에서 사각형의 각 측면에서 픽셀의 1/4을 사용했다고 생각합니다. 따라서 x 구성 요소의 경우 UV를 1 / (4 * widthOfTheAtlas)로, y 구성 요소의 경우 1 / (4 * heightOfTheAtlas)만큼 UV를 오프셋하십시오.


고맙지 만, 이미 언급했듯이 지오메트리는 정확히 인접 해 있습니다. 실제로 모든 좌표는 정확한 정수를 나타내므로 쉽게 알 수 있습니다. 여기에는 아틀라스가 사용되지 않습니다.
AshleysBrain

0

이를 3D 공간에서 해결하기 위해 Wolfgang Skyler의 제안과 텍스처 배열을 혼합했습니다. 각 타일 (120x120, 128x128)의 실제 텍스처 주위에 8 픽셀의 테두리를 두었습니다. 각 타일은 "랩핑 된"이미지로 채워지거나 확장 된면으로 채워질 수 있습니다. 샘플러는 이미지를 보간 할 때이 영역을 읽습니다.

이제 필터링 및 밉 매핑을 통해 샘플러는 여전히 전체 8 픽셀 경계를 지나서 쉽게 읽을 수 있습니다. 그 작은 문제를 잡기 위해 (지오메트리가 실제로 기울어 지거나 멀리있을 때 몇 픽셀에서만 발생하기 때문에 작습니다) 타일을 텍스처 배열로 나눕니다. 따라서 각 타일에는 고유 한 텍스처 공간이 있으며 클램핑을 사용할 수 있습니다 가장자리.

귀하의 경우 (2D / flat), 확실히 픽셀 완벽한 장면을 렌더링 한 다음 Nick Wiggil이 제안한대로 원하는 결과 부분을 뷰포트로 스케일링합니다.

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