Microsoft MVP성태의 닷넷 이야기
Graphics: 8. Unity Shader - Texture의 UV 좌표에 대응하는 Pixel 좌표 [링크 복사], [링크+제목 복사]
조회: 4090
글쓴 사람
홈페이지
첨부 파일
 

Unity Shader - Texture의 UV 좌표에 대응하는 Pixel 좌표

간단하게 예를 들어서, 0 ~ 1 사이로 정규화되어 있는 UV 좌표계에서 0.1에 해당하는 texture의 pixel(x,y) 위치를 알고 싶다는 것입니다. 이것은 UV 좌표계의 의미를 알면 유추해 낼 수 있습니다.

가령, 가로 1024 * 세로 768 이미지의 texture를 (0,0) ~ (1,1) UV 좌표로 매핑한 경우 다음과 같은 의미를 갖게 됩니다.

u    pixel
0 -> 0
1 -> 1024

v    pixel
0 -> 0
1 -> 768

따라서, 다음과 같은 비율로 알아낼 수 있습니다.

u:x = 1:1024
v:y = 1:768

만약 그중에 (0.1, 0.7) uv 좌표 값을 가지고 있다면 이것을 pixel 위치로 환산하면 다음과 같이 계산할 수 있습니다.

0.1:x = 1:1024
x = 1024 * 0.1 = 102.4
   = width of texture * u

0.7:y = 1:768
y = 768 * 0.7 = 537.6
   = height of texture * v

uv(0.1, 0.7) == xy(102.4, 537.6) ≈ (102, 538)


실제로 그런지 Unity에서 지구본을 texture로 사용했던 예제를 보겠습니다.

Unity로 실습하는 Shader
; https://www.sysnet.pe.kr/2/0/11607

Shader "My/basicShader"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag

    #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            sampler2D _MainTex;

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
}

그러니까, 위의 tex2D 함수는 2048 * 1024 크기의 지구 이미지를 texture로 사용했을 때, uv 좌표에 해당하는 texture의 컬러를 구해주고 있는 것입니다.

fixed4 frag(v2f i) : SV_Target
{
    fixed4 col = tex2D(_MainTex, i.uv);
    return col;
}

만약, 현재의 i.uv가 가리키고 있는 좌표보다 u 값으로 +10 pixel에 해당하는 컬러 값을 사용하고 싶다면 다음과 같이 하면 됩니다.

fixed4 frag(v2f i) : SV_Target
{
    float uPerX = 1.0 / 2048; // 1 / width
    float vPerY = 1.0 / 1024; // 1 / height

    float uOffset = 10 * uPerX;
    float vOffset = 0 * vPerY;

    float2 nextUVOffset = float2(uOffset, vOffset);
    fixed4 col = tex2D(_MainTex, i.uv + nextUVOffset);

    return col;
}

저렇게 하면, 지구본이 +10 픽셀만큼 회전한 것처럼 보입니다. 또는, u 값으로 +2048 pixel을 준다면 어떻게 될까요?

float uOffset = 2048 * xPerU;

결국 제자리로 오기 때문에 화면에는 아무런 변화가 없습니다.




그런데, shader 코드에 2048, 1024이라고 하드 코딩을 하는 것이 좀 그렇군요. ^^ 이것을 없애려면 Properties 영역으로 옮겨 변수 처리를 하면 됩니다. 물론 그래도 되지만, Unity에서는 "_TexelSize"라는 접미사를 붙이면 해당 텍스처의 width, height를 담고 있는 값을 알아서 전달해 줍니다.

예를 들어, 위의 코드에서는 텍스처 변수 명이 "_MainTex"였으므로 다음과 같이 선언해 주면 됩니다.

float2 _MainTex_TexelSize;

그리고 그 변수의 값은 각각 다음과 같이 설정이 됩니다.

Accessing shader properties in Cg/HLSL
; https://docs.unity3d.com/Manual/SL-PropertiesInPrograms.html

x contains 1.0/width
y contains 1.0/height
z contains width
w contains height

결국 이를 반영하면 다음과 같이 하드 코딩 없이 작성할 수 있습니다.

fixed4 frag(v2f i) : SV_Target
{
    float uPerX = _MainTex_TexelSize.x;
    float vPerY = _MainTex_TexelSize.y;

    float uOffset = 10 * uPerX; // x축으로 +10 pixel 위치
    float vOffset = 10 * vPerY; // y축으로 +10 pixel 위치

    float2 nextUVOffset = float2(uOffset, vOffset);
    fixed4 col = tex2D(_MainTex, i.uv + nextUVOffset);

    return col;
}

float2 UVtoXY(float2 uv, float2 texelSize)
{
    return float2(uv.x / texelSize.x, uv.y / texelSize.y);
}

float2 XYtoUV(float2 pos, float2 texelSize)
{
    return float2(pos.x * texelSize.x, pos.y * texelSize.y);
}




다음의 링크를 보면,

D3D이용 2D출력시 마법의 숫자 -0.5 에 대하여  
; http://blog.daum.net/gamza-net/16

실수 보정을 하는데 아마 이 때문인지 다음의 답글을 보면,

How to get precise pixel values form a Texture2D using uv coordinates.
; https://answers.unity.com/questions/1106031/how-to-get-precise-pixel-values-for-a-texture2d-us.html

(0.5를 빼지 않고) 더하는 것이 나옵니다.

u = x / width + 0.5 / width;
v = y / height + 0.5 / height;

pixel shader에서 저 작업이 필요한지는... 혹시 아시는 분은 덧글 부탁드립니다. ^^




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]





[최초 등록일: ]
[최종 수정일: 7/21/2018 ]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer@outlook.com

비밀번호

댓글 쓴 사람
 




... 16  17  18  19  20  21  [22]  23  24  25  26  27  28  29  30  ...
NoWriterDateCnt.TitleFile(s)
11682정성태9/5/20181538오류 유형: 484. Fakes를 포함한 단위 테스트 프로젝트를 빌드 시 CS1729 관련 오류 발생
11681정성태9/5/20182796Windows: 149. 다른 컴퓨터의 윈도우 이벤트 로그를 구독하는 방법 [2]
11680정성태9/2/20182420Graphics: 21. shader - _Time 내장 변수를 이용한 UV 변동 효과파일 다운로드1
11679정성태8/31/20181949.NET Framework: 792. C# COM 서버에 구독한 COM 이벤트를 C++에서 받는 방법파일 다운로드1
11678정성태8/29/20181618오류 유형: 483. 닷넷 - System.InvalidProgramException
11677정성태8/29/20181357오류 유형: 482. TFS - Could not find a part of the path '...\packages\Microsoft.AspNet.WebApi.5.2.5\.signature.p7s'.
11676정성태8/29/20182945.NET Framework: 791. C# - ElasticSearch를 위한 Client 라이브러리 제작파일 다운로드1
11675정성태8/29/20181888오류 유형: 481. The located assembly's manifest definition does not match the assembly reference.
11674정성태8/29/20182275Phone: 12. Xamarin - 기존 리모컨 기능을 핸드폰의 적외선 송신으로 구현파일 다운로드1
11673정성태8/28/20181843오류 유형: 480. Fritzing 실행 시 Ordinal Not Found 오류
11672정성태8/28/20181487오류 유형: 479. 윈도우 - 시스템 설정에서 도메인 참가를 위한 "Change" 버튼이 비활성화된 경우
11671정성태10/23/20183989사물인터넷: 39. 아두이노에서 적외선 송신기 기본 사용법파일 다운로드1
11670정성태10/17/20183128사물인터넷: 38. 아두이노에서 적외선 수신기 기본 사용법파일 다운로드1
11669정성태8/24/20182124개발 환경 구성: 394. 윈도우 환경에서 elasticsearch의 한글 블로그 검색 인덱스 구성
11668정성태8/28/20182186오류 유형: 478. 윈도우 업데이트(KB4458842) 이후 SQL Server 서비스 시작 오류
11667정성태8/28/20181825오류 유형: 477. "Use Unicode UTF-8 for worldwide language support" 옵션 설정 시 SQL Server 2016 설치 오류 [1]
11666정성태8/22/20181703사물인터넷: 37. 아두이노 - 코딩으로 대신하는 오실레이터 회로의 소리 출력파일 다운로드1
11665정성태8/22/20182445사물인터넷: 36. 오실레이터 회로 동작을 아두이노의 코딩으로 구현하는 방법파일 다운로드1
11664정성태8/22/20182712개발 환경 구성: 393. 윈도우 환경에서 elasticsearch의 한글 형태소 분석기 설치
11663정성태8/25/20183697개발 환경 구성: 392. 윈도우 환경에서 curl.exe를 이용한 elasticsearch 6.x 기본 사용법
11662정성태8/21/20181968사물인터넷: 35. 병렬 회로에서의 커패시터파일 다운로드1
11661정성태8/21/20181881사물인터넷: 34. 트랜지스터 동작 - 컬렉터-이미터 간의 저항 측정파일 다운로드1
11660정성태9/4/20181787사물인터넷: 33. 세라믹 커패시터의 동작 방식파일 다운로드1
11659정성태8/19/20181954사물인터넷: 32. 9V 전압에서 테스트하는 PN2222A 트랜지스터파일 다운로드1
11658정성태8/18/20183074사물인터넷: 31. 커패시터와 RC 회로파일 다운로드3
11657정성태8/21/20182427사물인터넷: 30. 릴레이(Relay) 제어파일 다운로드3
... 16  17  18  19  20  21  [22]  23  24  25  26  27  28  29  30  ...