귓바울 높이로 구현된 눈 쉐이더를 소개합니다.

8704 단어 Unity3DShaderLabUnity
이 기사는 KLab Advent Calendar 2019 22 일째 기사입니다.

소개



안녕하세요, 클라이언트 엔지니어 norm81입니다.

갓츠바르하이트 에서는 크리스마스 이벤트가 절찬 개최중입니다.
이번에는 크리스마스 이벤트에서 구현된 눈 쉐이더를 소개합니다.
소개하는 동작 확인된 환경은 Unity 2017.4.29f1입니다.

구현된 셰이더



・지면에 눈이 쌓이는 셰이더
・천장에 눈이 쌓이는 셰이더
・스크린 기반의 눈이 내리는 셰이더

norm81이 주로 담당한 것은 지상에 눈이 쌓이는 셰이더입니다만
그 이외에도 각 항에서 소개합니다.

지상에 눈이 쌓이는 셰이더




전용 마스크 테스크처를 사용하여 마스크의 흰색 부분에서,
머티리얼에 설정된 범위 값을 기반으로 차례로 표시됩니다.
정점마다 접선과 각도 계산하여 지붕에도 사용하고 있습니다.

마스크 텍스처


속성


관련 부분을 빼낸 셰이더

snow1.shader
sampler2D _HeightmapTex; // マスクテクスチャ
half _Snow; // Snow Level: レンジ域
half _SnowOffset; // Snow Offset: レンジ基準値オフセット
half _SnowSmooth; // Snow Smooth: 境界値付近のアルファ値
half4 _SnowColor; // Snow Color: 対象を上書きする色
half4 _SnowDirection; // Snow Ditection: 角度差の基準とする法線

v2f vert(appdata_t v)
{
    v2f f;

    // 省略
    float3 worldSpaceNormal = mul(unity_ObjectToWorld, v.normal).xyz;
    worldSpaceNormal = normalize(worldSpaceNormal);

    // NOTE: fragで計算した方がレンジの反映精度が高いが、計算回数の省略目的とstep境界値付近のぼかしにv2fの補間を使っている。
    float theta = dot(worldSpaceNormal, _SnowDirection.xyz);
    float threshold = (0.5 - _Snow) * 2.0;
    f.snowalpha = _SnowColor.a * (1 - step(theta, threshold));
    // 省略
    return f;
}

half4 frag(v2f f) : COLOR
{
    half3 color = tex2D(_MainTex, f.uv);

    // 省略
    half3 Heightmap = tex2D(_HeightmapTex, f.uv.xy);
    float snowHeight = (1.0 - Heightmap.r) + _Snow + _SnowOffset;
    float snowAlpha = f.snowalpha * saturate((snowHeight - 1.0 + 0.0001) / (_SnowSmooth + 0.0001)); // 0.0001: Check division by zero.
    color = lerp(color, _SnowColor.rgb, snowAlpha * step(1.0, snowHeight));
    // 省略
    return half4(color, 1.0);
}

천장에 눈이 쌓이는 셰이더




천장이라고 기재하고 있는 것은, 상면도의 마스크 텍스처를 사용하고 있기 때문입니다.
장점으로서 가시 범위를 잘 팔로우할 수 있으면 텍스처 최소 1장이므로
메모리를 절약할 수 있습니다.

마스크 텍스처


스크린 기반 눈이 내리는 셰이더




하위 호환성을 위해 GPU 인스턴스 대신
필요한 파티클 수로 나눈 격자 메쉬를 준비합니다.

준비한 메쉬의 정점 입력에 대해 아래의 시만테이크스를 유용한 형태로 베이크합니다.
・법선:좌표 변환 전의 기점 좌표
・칼라:애니메이션 좌표



그리고는, 자전 쉐이더로 파티클 요건으로서 좌표 변환·묘화 이외에
빌보드 처리 등을 실시하고 있습니다.

결론



눈 발자국을 만들거나 캐릭터 모양에 눈이 쌓이거나
모 스텔스 액션 게임과 같은 구현 같은 것을 해보고 싶습니다.

좋은 웹페이지 즐겨찾기