1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

3D textureを使ったブレンドアニメーション

Last updated at Posted at 2022-10-22

3D texture

サイバーエージェントさんのUnity用エフェクトシェーダについての記事を読んで、Unity上で3Dテクスチャが簡単に作成できるようになっているのを知りました。
これはスプライトアニメーションに使えそうです。さっそく実装してみました。

左が9パターンにアニメーション(ブレンドあり)、中央がモデルアニメーション、右が通常のスプライトアニメーションです。
アニメーションパターンが多い場合はそれほど変わり映えしませんし、少ない場合でも変にブレると気持ち悪いということもあると思いますが、使い方によっては良い効果が得られるのではないかと思います。

作成方法-Flipbook Animation

まずはアニメーションパターンのテクスチャを作成します。
Unityではテクスチャシートアニメーションや Flipbook Animation などと呼ばれています。
左上から右下にアニメーションする一連のパターンを並べておきます。
test3x3.png
これをUnityに読み込むとInspectorにImport Settingsが現れるので、
Texture Shapeを3Dにし、行および列の数を3にします。
またGenerate Mipmapsのチェックを外しておきます。
これを外しておかないと、スプライトを遠くに表示した際に複数のコマがブレンドされて表示されます。
image.png
Apply するとテクスチャシートが3Dテクスチャ化されます。
image.png
ここでSliceのタブを選択し、Zの値を変更するとアニメーションを確認することができます。
image.png

表示方法-Shader

続いて、3Dテクスチャに対応したシェーダーを用意します。
基本的には普通のテクスチャを表示するのと同じですが、UVに.z値があります。
また、通常はOffset.Z=0がパターンの中央値なのですが、指定しやすいように0がパターンの先頭になるようにしておきます。

Shader "Unlit/VolumeTransparentForAnim"
{
  Properties
  {
    _Volume("Volume", 3D) = "" {}
    _Scale ("Scale (x, y, z, and w=mul)", vector) = (1,1,1,1)
	_Offset ("Offset (x, y, z, and w=div)", vector) = (0,0,0,1)
  }

  CGINCLUDE
  #include "UnityCG.cginc"

  struct appdata
  {
    half4 vertex : POSITION;
  };

  struct v2f
  {
    half4 vertex : SV_POSITION;
    half3 uv : TEXCOORD0;
  };

  sampler3D _Volume;
  half4 _Scale;
  half4 _Offset;

  v2f vert(appdata v)
  {
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    half4 sclVec = v.vertex;
    sclVec.xyz /= _Scale.xyz*_Scale.w;
    half4 ofs = _Offset+half4(0,0,(_Offset.w-1)/2+1,0);
    o.uv = sclVec.xyz + (ofs.xyz / ofs.w) + 0.5;
    return o;
  }

  fixed4 frag(v2f i) : SV_Target
  {
    return tex3D(_Volume, i.uv);
  }
  ENDCG

  SubShader
  {
    Tags 
    { 
      "RenderType" = "Transparent" //"Opaque" // 
	  "Queue" = "Transparent" // "Geometry" // 
    }

    Pass
    {
	  Blend SrcAlpha OneMinusSrcAlpha
      ColorMask RGB
	  ZWrite Off
      Cull Back
      Offset 0,0
      CGPROGRAM
      #pragma vertex vert
      #pragma fragment frag
      ENDCG
    }
  }
}

上記shaderを使用したMaterialを作成し、Vokumeに3Dテクスチャを、Offset.wに分割数の9を入力します。
プレビューモデルをQuadにしておいて、Offset.Zにパターン番号を入れるとそのパターンが表示されます。
image.png
Z=1.5を入力するとパターン1と2がブレンドされて表示されるのがわかると思います。
image.png

使用方法-Script

スクリプト上から利用する場合は、マテリアルに対してSetVector("_Offset", vec);のようにOffsetを渡せばOKです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(MeshRenderer))]
public class Tex3DAnim : MonoBehaviour
{
    [SerializeField] float m_DivNum = 9f;
    [SerializeField, Range(0.1f, 32f)] float m_speedGain = 16f;
    [SerializeField] bool m_isStep = false;
    Material m_mat;
    Vector4 m_vec;
    float m_ptn;

    void Start()
    {
        MeshRenderer mr = GetComponent<MeshRenderer>();
        m_mat = mr.material;
        m_vec = new Vector4(0, 0, 0, m_DivNum);
    }

    void Update()
    {
        m_ptn += Time.deltaTime * m_speedGain;
        m_vec.z = (m_isStep? Mathf.Floor(m_ptn) : m_ptn);
        m_mat.SetVector("_Offset", m_vec);
    }
}

おまけ-Appendix

比較用に4x4のテクスチャシートも置いておきます。test4x4.png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?