2016-09-07 2 views
6

나는 다음 코드를 사용하여 Unity3D의 자동 선형 필터링 알고리즘을 복제하기 위해 노력하고있어 :쌍 선형 필터링이 아닌 경우이 기술은 무엇입니까?

fixed4 GetBilinearFilteredColor(float2 texcoord) 
{ 
    fixed4 s1 = SampleSpriteTexture(texcoord + float2(0.0, _MainTex_TexelSize.y)); 
    fixed4 s2 = SampleSpriteTexture(texcoord + float2(_MainTex_TexelSize.x, 0.0)); 
    fixed4 s3 = SampleSpriteTexture(texcoord + float2(_MainTex_TexelSize.x, _MainTex_TexelSize.y)); 
    fixed4 s4 = SampleSpriteTexture(texcoord); 

    float2 TexturePosition = float2(texcoord)* _MainTex_TexelSize.z; 

    float fu = frac(TexturePosition.x); 
    float fv = frac(TexturePosition.y); 

    float4 tmp1 = lerp(s4, s2, fu); 
    float4 tmp2 = lerp(s1, s3, fu); 

    return lerp(tmp1, tmp2, fv); 
} 

fixed4 frag(v2f IN) : SV_Target 
{ 
    fixed4 c = GetBilinearFilteredColor(IN.texcoord) * IN.color; 
    c.rgb *= c.a; 
    return c; 
} 

은 내가 선형을 위해 거기 밖으로 본 유일한 사람이기 때문에 올바른 알고리즘으로 사용하던 생각했다. 포인트 필터링에 있고 (기본 스프라이트 쉐이더에서 maded) 사용자 정의 선형 쉐이더를 사용하여 :

  • 1º 질감을 :하지만이 중복 같은 질감과 단결을 사용했습니다.
  • 2 º 질감 : 기본 스프라이트 쉐이더

와 이중 선형 필터에 그리고 이것은 결과입니다

enter image description here

당신은 서로 다른 것을보고 일부가 수 스프라이트가 Z 축에서 회전 할 때 중심을 벗어나게 만드는 내 사용자 정의 셰이더에서의 위치 이동.

내가 잘못하고있는 것에 대한 아이디어가 있습니까? Unity3D가 무엇을하고 있는지에 대한 아이디어가 있습니까? Unity3D 기본 필터링에 적합한 다른 알고리즘이 있습니까?

솔루션

여기 검색 다른 사람들을위한 니코의 코드 전체 코드 솔루션 업데이트 :

fixed4 GetBilinearFilteredColor(float2 texcoord) 
{ 
    fixed4 s1 = SampleSpriteTexture(texcoord + float2(0.0, _MainTex_TexelSize.y)); 
    fixed4 s2 = SampleSpriteTexture(texcoord + float2(_MainTex_TexelSize.x, 0.0)); 
    fixed4 s3 = SampleSpriteTexture(texcoord + float2(_MainTex_TexelSize.x, _MainTex_TexelSize.y)); 
    fixed4 s4 = SampleSpriteTexture(texcoord); 

    float2 TexturePosition = float2(texcoord)* _MainTex_TexelSize.z; 

    float fu = frac(TexturePosition.x); 
    float fv = frac(TexturePosition.y); 

    float4 tmp1 = lerp(s4, s2, fu); 
    float4 tmp2 = lerp(s1, s3, fu); 

    return lerp(tmp1, tmp2, fv); 
} 

fixed4 frag(v2f IN) : SV_Target 
{ 
    fixed4 c = GetBilinearFilteredColor(IN.texcoord - 0.498 * _MainTex_TexelSize.xy) * IN.color; 
    c.rgb *= c.a; 
    return c; 
} 

그리고 결과에 이미지 테스트 :

enter image description here

정확히 0.5를 빼지 않는 이유는 무엇입니까?

테스트를 수행하면 몇 가지 엣지 케이스가 나타납니다 (픽셀 - 1).

답변

6

실제로 무엇을하고 있는지 자세히 살펴 보겠습니다. 나는 시각화하기가 쉽기 때문에 1D 경우를 고수 할 것입니다.

픽셀 배열과 텍스처 위치가 있습니다. 나는, _MainTex_TexelSize.z이 픽셀 좌표를주는 방식으로 설정되어 있다고 가정합니다. 당신은 픽셀 2를 얻을 것이다 (가까운 포인트 샘플링을 가정) 당신의 샘플링으로

Pixels

: 이것은 당신이 (상자는 상자에 픽셀 공간 좌표 아래의 픽셀 수와 숫자를 픽셀 수를 나타냅니다) 무엇을 얻을 그러나 보간 좌표가 lerp 인 것은 실제로 잘못된 것입니다. 텍스처 위치의 소수 부분 (예 : 0.8)을 전달하지만 0.3 (= 0.8 - 0.5)이어야합니다. 이것에 대한 추론은 아주 간단합니다 : 픽셀의 중심에 올랐다면 픽셀 값을 사용하고 싶습니다. 두 픽셀 사이의 중간에 위치하는 경우 두 픽셀 값의 평균 (즉, 보간 값 0.5)을 사용하려고합니다. 지금 당장 당신은 기본적으로 왼쪽 절반 픽셀만큼 오프셋되어 있습니다.첫 번째 문제를 해결하면

, 두 번째 일이 :

이 경우

Pixels

, 당신은 실제로 픽셀 1과 2 사이에 혼합 할하지만 당신은 항상 오른쪽으로 이동하기 때문에 귀하의 샘플링, 당신은 2와 3 사이에 조화를 이룰 것입니다. 다시, 잘못된 보간 값.

해결책은 아주 간단해야한다 :

fixed4 c = GetBilinearFilteredColor(IN.texcoord - 0.5 * _MainTex_TexelSize.xy) * IN.color; 
: 텍스처의 픽셀 폭 빼기 절반은 다음 (당신의 변수가 내가 생각하는 일을 유지한다고 가정) 단지 아마 그것으로 무엇을하기 전에 좌표

결과가 다른 또 다른 이유는 Unity가 실제로 다른 필터를 사용하는 것일 수 있습니다. bicubic (그러나 나는 모른다). 또한 밉맵을 사용하면 결과에 영향을 미칠 수 있습니다.