테이퍼링 된 생성 된 메시에서 지그재그 UV 매핑 아티팩트를 어떻게 수정합니까?


10

커브를 기반으로 절차 적 메쉬를 만들고 있는데 아래에서 볼 수 있듯이 메쉬 크기가 커브 전체에서 작아집니다.

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

그리고 문제는 크기가 변함에 따라 UV가 지그재그로 표시됩니다 (메쉬의 크기가 커브 전체에서 동일 할 때 완벽하게 작동 함).

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

 Vertices.Add(R);
 Vertices.Add(L);
 UVs.Add(new Vector2(0f, (float)id / count));
 UVs.Add(new Vector2(1f, (float)id / count));
 start = Vertices.Count - 4;
          Triangles.Add(start + 0);
                 Triangles.Add(start + 2);
                 Triangles.Add(start + 1);
                 Triangles.Add(start + 1);
                 Triangles.Add(start + 2);
                 Triangles.Add(start + 3);

 mesh.vertices = Vertices.ToArray();
         //mesh.normals = normales;
         mesh.uv = UVs.ToArray();
         mesh.triangles = Triangles.ToArray();

이 문제를 어떻게 해결할 수 있습니까?


무엇 idcount? 무엇을 UVs.ToArray()합니까? 정점과 텍스처 좌표를 카드에 어떻게 업로드합니까?
user1118321

문맥에서 @ user1118321 id은 스트립을 따라 모든 크로스바에서 현재 세그먼트의 인덱스이며 count총 위치입니다. List<T>.ToArray()목록에있는 모든 항목의 형식화 된 배열을 반환합니다 (여기서는 a Vector2[]). 이 데이터 버퍼는 마지막 몇 줄 의 Mesh인스턴스 mesh에 할당하여 렌더링 시스템에서 사용할 수 있습니다 . 그러나 이것의 어느 것도 코드에서 특히 흥미로운 부분은 아닙니다 : 꼭짓점을 선택하는 방법. 이러한 세부 사항은 더 유용 할 것입니다. ;)
DMGregory

그것은 내 가정이지만, 때로는 가정이 잘못되기 때문에 설명을 요구했습니다. 나는 과거에 내 자신의 코드에서 이와 비슷한 것을 보았는데 count실제로 다각형 대신 정점을 의미한다는 것을 깨달았습니다 . 우리가 생각하는 모든 것이 실제로 진행되고 있는지 확인하십시오.
user1118321

답변:


13

일반적인 UV 매핑은 아핀 변환 입니다. 즉, 3D 공간과 텍스처 공간 사이의 각 삼각형 매핑에는 회전, 평행 이동, 스케일링 / 스쿼시 및 스큐가 포함될 수 있습니다 (예 : 동종 행렬 곱셈으로 수행 할 수있는 모든 작업)

아핀 변환에 대한 것은 그들이하고 있다는 것이다 균일 우리가 정점에 가까운 질감에 적용되는 회전, 번역, 규모, 스큐 우리가 어떤 하나의 삼각형 내에서, 근처 정점 B를 적용 것과 동일합니다 - 자신의 전체 도메인에서이. 한 공간에서 평행 한 선은 다른 공간에서 평행 한 선으로 매핑되며 수렴 / 발산되지 않습니다.

그러나 적용하려는 점진적인 테이퍼링은 균일하지 않습니다. 텍스처의 평행선을 메시의 수렴 선에 매핑합니다. 즉, 스트립을 따라 내려감에 따라 밴드 전체에서 측정 된 텍스처의 스케일이 지속적으로 변경됩니다. 이는 2D UV 매핑의 아핀 변환보다 정확하게 표현할 수있는 것 이상입니다. 인접한 정점 사이에 2D uv 좌표를 보간하면 전체 가장자리를 따라 하나의 일관된 배율을 얻을 수 있으며, 대각선 가장자리는 스트립 아래로 이동함에 따라 축소되어야합니다. 그 불일치는이 뒤틀린 지그재그를 만드는 것입니다.

이 문제는 직사각형을 사다리꼴에 평행하게 만들려고 할 때마다 발생합니다-평행 한 변을 수렴하는 변에 :이 작업을 수행하는 아핀 변환은 없으므로 조각으로 근사화하여 이음새가 보입니다.

대부분의 경우 형상을 더 추가하여 효과를 최소화 할 수 있습니다. 헤링본 패턴으로 배열 된 삼각형의 대각선으로 스트립의 길이를 따라 세분의 수를 늘리고 스트립을 폭을 따라 두 개 이상의 세그먼트로 나누면 효과가 눈에 띄지 않게 될 수 있습니다. 우리가 아핀 변환을 사용하는 한 항상 어느 정도 존재합니다.

그러나 그 주위에 방법이 있습니다. 직사각형 벽과 바닥에서 사다리꼴을 원근감있게 그리는 3D 렌더링에 사용하는 것과 동일한 트릭을 사용할 수 있습니다. 투영 좌표를 사용 합니다 !

텍스처링하기 : 지그재그 인공물로 정상적인 아핀 텍스처링의 예

프로젝션 텍스처링 : 아티팩트를 수정하는 투사 텍스트 링의 예

이렇게하려면 세 번째 uv 좌표 (uvw)를 추가하고 셰이더를 수정해야합니다.

각 지점에 스케일 계수가 주어지면 (즉, 해당 지점에서 스트립 폭과 동일) 일반 2D uv 좌표에서 3D 투영 uvw 좌표를 다음과 같이 구성 할 수 있습니다.

Vector3 uv3 = ((Vector3)uv2) * scale;
uv3.z = scale;

이 3D UV 좌표를 메시에 적용하려면 Vector3 과부하 메시를 사용해야합니다 .SetUVs (int channel, List uvs)

그리고 3D 텍스처 좌표를 기대하도록 셰이더의 입력 구조체를 변경하십시오 (기본 unlit 셰이더를 사용하여 표시됨).

struct appdata
{
    float4 vertex : POSITION;
    float3 uv : TEXCOORD0; // Change float2 to float 3.
};
// Also do this for the uv sent from the vertex shader to the fragment shader.

또한 정점 셰이더에서 TRANSFORM_TEX 매크로를 잘라 내야합니다. 2D uv를 기대하기 때문입니다.

// o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.uv = v.uv;
// If you define a float4 with the special name _MainTex_ST, 
// you can get the same effect the macro had by doing this:
o.uv.xy = o.uv.xy * _MainTex_ST.xy + _MainTex_ST.zw;

마지막으로 텍스처 샘플링을 위해 2D 텍스처 좌표로 돌아가려면 조각 쉐이더 에서 세 번째 좌표로 나눕니다 .

float2 uv = i.uv.xy / i.uv.z;

동일한 숫자를 곱하여 원하는 2D 좌표에서이 3D uvw 좌표를 만들었으므로 두 작업이 취소되고 원래의 원하는 2D 좌표로 돌아 오지만 정점 사이의 비선형 보간으로 돌아갑니다. :디

버텍스 셰이더가 아닌 프래그먼트마다이 분할을 수행하는 것이 중요합니다. 정점마다 수행되면 각 모서리를 따라 선형으로 결과 좌표를 보간하는 것으로 돌아가서 투영 좌표로 도입하려는 비선형 성을 잃어 버렸습니다!


안녕하세요, 저는 꽤 오랫동안 같은 문제로 어려움을 겪어 왔으며, 이것이 정확히 나에게 일어나는 것처럼 보입니다. 유일한 차이점은 내가 threejs에서 일하고 있고 통일이 아니라는 것입니다. 우리는 삼각형의 수를 늘려 문제를 해결했지만 여전히 투영 텍스처링을 시도하고 싶습니다. threejs에서 이것을 구현하기 시작하는 방법을 알고 있습니까? 감사합니다!
Dživo Jelić

1
거의 같은 방식입니다. 제수를 저장하려면 세 번째 텍스처 좌표가 필요하며 조각 쉐이더에서 나눗셈을 수행하십시오. 이것을 케이스에 적용하는 데 문제가 있었다면, 새로운 질문을하면 코드 샘플을 포함시킬 수 있습니다. 메시를 지금까지 그리는 방법을 보여 주면 답을 얻을 수 있습니다.
DMGregory

제수를 세 번째 좌표로 저장해야합니까 (그리고 그 변경 구조로 인해 threejs에서 수행하는 방법을 모르는 TRANSFORM_TEX 매크로를 잘라 내야합니다) 또는 제수를 정점 셰이더의 속성으로 전달할 수 있습니까 그런 다음 분할에 사용할 수있는 조각 쉐이더에 대한 다양한 변형이 있습니까?
Dživo Jelić가

TRANSFORM_TEX는 Unity 매크로입니다. three.js에는 해당 항목이 없으므로 잘라낼 것이 없습니다. 보간 된 uv 좌표와 제수가 프래그먼트 셰이더에 도달하는 한 실제로 어떻게 거기에 도달했는지는 중요하지 않습니다. 지금까지 속성 / 변수로 제공하는 데 문제가 있습니까?
DMGregory

나는 그것이 가능하다는 것을 확인할 때까지 시간을 낭비하고 싶지 않았으므로 아직 시도하지 않았습니다. 마지막 질문 하나만으로, 제수는 조각 쉐이더에 도달하면 보간됩니다. 맞습니까? 두 정점 사이의 픽셀에서 원래 값이 아닌 보간 된 값이 될 것입니까? 왜 UV를 곱한 다음 나누는 것이 도움이되는지 머리를 감싸는 데 어려움을 겪고 있습니다. : slightly_smiling_face : 도와 주셔서 감사합니다!
Dživo Jelić
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.