모델의 애니메이션 텍스처; 셰이더를 작성하는 방법?


9

로켓 리그를 보면서 애니메이션 데칼과 바퀴가 있음을 알았습니다.

영상.

위 이미지의 효과와 비슷한 것을 구현하고 싶습니다.

휠 효과를 위해 Unity Shader를 작성하는 방법은 무엇입니까?

셰이더에 대해 잘 모르지만 애니메이션 효과를 위해 표준 Unity 셰이더를 편집 할 수 있습니까?


3
셰이더는 스크롤 텍스처처럼 단순한 것에서도 확실히 해결책입니다. Unity에는 _Time(버텍스) 셰이더의 텍스처 좌표에 추가 할 수 있는 내장 변수가있어 스크롤링 효과를 저렴하게 얻을 수 있습니다. 육각형 효과도 매우 간단합니다. 하나의 효과 만 강조하기 위해 질문을 편집하고 "Unity 셰이더에서 어떻게 구현하겠습니까?"라고 물으면 도움이 될 수 있습니다. 셰이더가 라이팅 / 섀도 잉에 반응해야하는지 여부를 지정해야합니다. 라이팅 / 섀도 잉은 작성 방법에 영향을 미칩니다.
DMGregory

정보에 대해서 감사드립니다. 내 질문을 변경했는데 조금 더 좋습니까? 조명과 그림자에 대해 잘 모르므로 셰이더를 더 잘 이해할 때까지 지금은 그만 두었습니다. 나는 그것들을 원할 것 같지만 표준 쉐이더에서 부품을 복사 할 수 있습니까?
JacketPotatoeFan

3
오늘 밤 조금 후에 답변으로 확장 해 보겠습니다 (누군가가 지금 답변을 원한다면 저를 이길 수는 있지만 자유롭게 느끼십시오!)-일반적으로 조명을 "Surface Shader"로 사용하는 Unity 셰이더를 작성합니다. 조명이 필요하지 않은 것은 종종 "Unlit Shader"로 작성하는 것이 더 간단합니다. 그 바퀴가 꺼져있는 것처럼 보입니다 (가장자리에 약간의 그림자가 SSAO처럼 보입니다). 그래서 초보자를 위해 그림에서 조명을 비워 두었습니다. 여기에 표시된 기하학적 패턴을 원하십니까? 아니면 임의의 텍스처를 바깥쪽으로 스크롤하여 무지개 색조로 만들 수 있습니까?
DMGregory

정말 고마워요, 당신이 저를 시작하기 위해 줄 수있는 어떤 정보라도 훌륭합니다. 셰이더를 작성할 수있는 사람들을 정말 존경하고, Unity Shaders에 대한 몇 가지 기사를 살펴 봤으며 매우 혼란 스러웠습니다. 텍스쳐 (또는 텍스쳐 uv)를 스크롤하는 것만으로도 충분하고 색조를 낼 수 있다고 생각합니다.
JacketPotatoeFan

답변:


13

이것을 몇 층으로 구성하여 어떻게 구성되는지 볼 수 있습니다.

Create --> Shader --> Unlit프로젝트 메뉴에서 에셋 메뉴 또는 마우스 오른쪽 버튼 클릭 컨텍스트 메뉴에서 선택하여 Unity에서 새 셰이더를 생성하는 것으로 시작하십시오 .

상단 블록 _ScrollSpeeds에는 텍스처가 각 방향으로 얼마나 빨리 움직이는 지 제어하는 ​​파라미터가 추가됩니다 :

Properties
{
    _MainTex ("Texture", 2D) = "white" {}
    _ScrollSpeeds ("Scroll Speeds", vector) = (-5, -20, 0, 0)
}

그러면 재료 관리자에서 이름이 "Scroll Speeds"( 스크립트에 변수 public또는 Serialized변수를 추가하는 것과 유사 함)와 함께 새로운 4 성분 부동 속성이 노출됩니다.MonoBehaviour

다음으로 정점 셰이더에서이 변수를 사용 o.uv하여 기본 셰이더에 두 줄만 추가 하여 텍스처 좌표 ( ) 를 이동합니다 .

sampler2D _MainTex;
float4 _MainTex_ST;
// Declare our new parameter here so it's visible to the CG shader
float4 _ScrollSpeeds;

v2f vert (appdata v)
{
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.uv = TRANSFORM_TEX(v.uv, _MainTex);

    // Shift the uvs over time.
    o.uv += _ScrollSpeeds * _Time.x;

    UNITY_TRANSFER_FOG(o,o.vertex);
    return o;
}

쿼드 (그것은 Kenney멋진 무료 기린 질감으로 )를 때리고 다음을 얻습니다.

반복되는 기린이있는 쿼드.

텍스처가 링에서 바깥쪽으로 스크롤되도록하려면 거미줄처럼 세분화 된 메쉬를 사용하면 uv v 좌표가 가운데에서 증가합니다. 그러나 그것은 그 자체로 톱날 모양의 인공물을 줄 것입니다. 대신 조각 당 UV를 계산하는 방법을 보여 드리겠습니다.

삼각법과 길이 연산 (기본 수학보다 비싸다)과 조각 당 텍스 코딩을 계산할 때 하드웨어에서 텍스처 데이터를 보간하는 것보다 예측 및 캐시하는 것이 비효율적이기 때문에 약간 더 비쌉니다. 정점 사이. 그러나 이와 같은 작은 특수 효과의 경우에는 과도하지 않습니다.

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

    // Shift the UVs so (0, 0) is in the middle of the quad.
    o.uv = v.uv - 0.5f;

    UNITY_TRANSFER_FOG(o,o.vertex);
    return o;
}

fixed4 frag (v2f i) : SV_Target
{
    // Convert our texture coordinates to polar form:
    float2 polar = float2(
           atan2(i.uv.y, i.uv.x)/(2.0f * 3.141592653589f), // angle
           length(i.uv)                                    // radius
        );

    // Apply texture scale
    polar *= _MainTex_ST.xy;

    // Scroll the texture over time.
    polar += _ScrollSpeeds.xy * _Time.x;

    // Sample using the polar coordinates, instead of the original uvs.
    // Here I multiply by MainTex
    fixed4 col = tex2D(_MainTex, polar);

    // apply fog
    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}

이것은 우리에게 이와 같은 것을 제공합니다 (여기서 재료의 타일링 매개 변수를 늘려서 진행 상황을 명확하게 나타냅니다-원 주위에 타일의 단일 반복 만 감싸는 것은 왜곡되고 이상하게 보입니다)

쿼드의 중심에서 바깥쪽으로 발산하는 기린

마지막으로 스크롤 그라디언트로 텍스쳐를 칠하기 위해 그라디언트를 두 번째 텍스쳐로 추가하고 곱하면됩니다.

먼저 맨 위에 새로운 텍스처 매개 변수를 추가합니다 :

Properties
{
    _MainTex ("Texture", 2D) = "white" {}
    _TintTex("Tint Texture", 2D) = "white" {}
    _ScrollSpeeds ("Scroll Speeds", vector) = (-5.0, -20.0, 0, 0)
}

CG 셰이더가 볼 수 있도록 CGPROGRAM 블록에 선언하십시오.

sampler2D _MainTex;
float4 _MainTex_ST;

// Declare our second texture sampler and its Scale/Translate values
sampler2D _TintTex;
float4 _TintTex_ST;

float4 _ScrollSpeeds;

그런 다음 프래그먼트 셰이더를 업데이트하여 두 텍스처를 모두 사용하십시오.

fixed4 frag(v2f i) : SV_Target
{
    float2 polar = float2(
           atan2(i.uv.y, i.uv.x) / (2.0f * 3.141592653589f), // angle
           length(i.uv)                                    // radius
        );

    // Copy the polar coordinates before we scale & shift them,
    // so we can scale & shift the tint texture independently.
    float2 tintUVs = polar * _TintTex_ST.xy;
    tintUVs += _ScrollSpeeds.zw * _Time.x;

    polar *= _MainTex_ST.xy;
    polar += _ScrollSpeeds.xy * _Time.x;

    fixed4 col = tex2D(_MainTex, polar);
    // Tint the colour by our second texture.
    col *= tex2D(_TintTex, tintUVs);

    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}

그리고 지금 우리 기린은 정말 어색해집니다.

멀리서 ...

질감과 스크롤 속도를 약간 더 예술적으로 선택하면 질문에 표시된 것과 매우 유사한 효과를 만들 수 있습니다.


위에 표시된 버전에서 두 가지 작은 아티팩트가 나타날 수 있습니다.

  • 원 중심 근처의면은 늘어나거나 마른 체형으로 뾰족 해지며 바깥쪽으로 움직일 때 얼굴이 찌그러지고 넓어집니다.

    이 왜곡은 주변에 고정 된 수의면이 있기 때문에 발생하지만 반경이 증가함에 따라 그 둘레가 넓어지고 높이는 동일하게 유지됩니다.

    텍스처 샘플의 수직 성분을 대수 곡선을 따르도록 리 맵핑하여이 문제를 해결할 수 있습니다. 따라서 반경이 증가함에 따라 텍스처의 반복이 더 멀어지고 중심을 향하여 서로 더 가까워집니다. (실제로 이것은 우리에게 작고 작은 기린의 무한 회귀를 제공합니다 ...)

  • 쿼드의 왼쪽 가운데에 1 개 또는 2 개의 흐릿한 픽셀 행이 있습니다.

    이것은 GPU가 인접한 두 개의 텍스처 샘플 좌표를보고 어떤 필터링을 사용해야하는지 파악하기 때문에 발생합니다. 샘플들이 서로 가까이있을 때, 텍스처가 크게 / 닫히는 것을 나타내고 가장 상세한 밉 레벨을 보여줍니다. 샘플이 멀리 떨어져있을 때, 텍스처를 작은 줌이나 멀리서 보여 주어야한다고 생각하고, 더 작은 / 흐릿한 밉맵에서 샘플링하여 반짝이는 앨리어싱 인공물을 얻지 않도록합니다.

    문제는 여기에서 -180도에서 180도까지 극좌표의 랩 어라운드 지점에 있습니다. 따라서 숫자 좌표로 인해 멀리 떨어져있는 것처럼 보이더라도 반복 텍스처 공간에서 매우 유사한 점에서 실제로 샘플링하고 있습니다. 이를 해결하기 위해 자체 샘플링 그래디언트 벡터를 제공 할 수 있습니다.

이러한 수정 사항이있는 버전은 다음과 같습니다.

fixed4 frag(v2f i) : SV_Target
{
    float2 polar = float2(
           atan2(i.uv.y, i.uv.x) / (2.0f * 3.141592653589f), // angle
           log(dot(i.uv, i.uv)) * 0.5f                       // log-radius
        );

    // Check how much our texture sampling point changes between
    // neighbouring pixels to the sides (ddx) and above/below (ddy)
    float4 gradient = float4(ddx(polar), ddy(polar));

    // If our angle wraps around between adjacent samples,
    // discard one full rotation from its value and keep the fraction.
    gradient.xz = frac(gradient.xz + 1.5f) - 0.5f;

    // Copy the polar coordinates before we scale & shift them,
    // so we can scale & shift the tint texture independently.
    float2 tintUVs = polar * _TintTex_ST.xy;
    tintUVs += _ScrollSpeeds.zw * _Time.x;

    polar *= _MainTex_ST.xy;
    polar += _ScrollSpeeds.xy * _Time.x;

    // Sample with our custom gradients.
    fixed4 col = tex2Dgrad(_MainTex, polar, 
                           _MainTex_ST.xy * gradient.xy,
                           _MainTex_ST.xy * gradient.zw
                         );

    // Since our tint texture has its own scale,
    // its gradients also need to be scaled to match.
    col *= tex2Dgrad(_TintTex, tintUVs,
                          _TintTex_ST.xy * gradient.xy,
                          _TintTex_ST.xy * gradient.zw
                         );

    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}

2
몇 가지 작은 개선 사항이 있습니다. 1) v 방향에 대수 곡선을 사용하면 바깥쪽으로 스크롤 할 때 질감이 모양을 유지하는 데 도움이됩니다 (중간 지점으로 좁히는 대신 작은 사본의 무한 체인을 얻을 수 있습니다) 2) 자신의 텍스처 그라디언트를 계산하고 사용 tex2Dgrad하여 각도가 -pi에서 + pi (왼쪽의 흐릿한 픽셀의가는 선) 주위를 감싸는 필터링 아티팩트 를 수정합니다. 다음은 파란색이 더 진한 터치 결과입니다.
DMGregory

놀랍게도 감사합니다. 셰이더는 내가 절대 쓸 수없는 무언가라고 생각합니다 (특히 "극성"에 대해 한 것과 같은 것들입니다. 수학 자료는 기본 수학 기술 만 가지고 있기 때문에 나에게는 아무 의미가 없습니다).
JacketPotatoeFan

1
그런 사람들은 보통 찾는 것입니다. ;) 키보드를 롤오프 할 정도로 충분합니다. 그래도 다른 수학 함수를 가지고 놀아보고 결과를 살펴보십시오. 수학적으로 기하학적으로 수행 한 작업을 시각화하는 데 도움이되는 이와 같은 도구를 사용하면 연습을 처음부터 수행 할 수 있습니다. (특히 셰이더가 아니라 WhiteCap이라는 오래된 WinAmp Visualiser ...) 셰이더 수학이 끔찍하게 잘못 될 때조차도보기에는 이상하게 시원합니다. : D
DMGregory
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.