イラスト、モデリング、Unity、VR関連

unityとかblenderとかvr関連の作業メモ

shader ジオメトリシェーダ・サンプル

 

 

++参考

HoloLens で使える Near Clip 表現について解説してみた - 凹みTips

ジオメトリシェーダ入門 - e.blog

 

++コード

上記の参考サイトのコードをカスタム・補完したものです

 

Shader "Custom/GeoSample"
{

  Properties
  {
      _Method("DestructionMethod", Float) = 0
      _Destruction("Destruction Factor", Range(0.0, 10.0)) = 0.0
      _UpFactor("Up Factor", Range(0.0, 10.0)) = 0.2
      _PositionFactor("Position Factor", Range(0.0, 10.0)) = 0.2
      _RotationFactor("Rotation Factor", Range(0.0, 10.0)) = 1.0
      _ScaleFactor("Scale Factor", Range(0.0, 10.0)) = 1.0
      _MainTex("Texture", 2D) = "white" {}
  }

  SubShader{

    Pass{

      CGPROGRAM
      #pragma vertex vert
      #pragma geometry geom
      #pragma fragment frag
      #pragma multi_compile _METHOD_PROPERTY _METHOD_CAMERA

      #include "UnityCG.cginc"

      #define PI 3.1415926535

      fixed _Destruction;
      fixed _PositionFactor;
      fixed _RotationFactor;
      fixed _UpFactor;
      fixed _ScaleFactor;
      fixed _AlphaFactor;
      fixed _StartDistance;
      fixed _EndDistance;

      uniform sampler2D _MainTex;
      uniform fixed4 _MainTex_ST;
			uniform uint _VID;

      struct appdata_t
      {
          float4 vertex : POSITION;
          float4 normal : NORMAL;
          fixed4 color : COLOR;
          float2 texcoord : TEXCOORD0;
					float2 vid : TEXCOORD1;
          UNITY_VERTEX_INPUT_INSTANCE_ID
      };

      struct g2f
      {
          float4 vertex : SV_POSITION;
          fixed4 color : COLOR;
          float2 texcoord : TEXCOORD0;
      };

      appdata_t vert(appdata_t v,uint vid : SV_VertexID)
      {
					v.vid = vid;
          return v;
      }

      float rand(float2 co){
        return frac(sin(dot(co.xy ,float2(12.9898,78.233))) * 43758.5453);
      }

      [maxvertexcount(3)]
      void geom(triangle appdata_t input[3], inout TriangleStream stream){
        // ポリゴンの中心を計算。
        // ポリゴン単位で計算を行えるため、「ポリゴンの中心位置」も計算可能です。
        float3 center = (input[0].vertex + input[1].vertex + input[2].vertex) / 3;

        // ポリゴンの辺ベクトルを計算し、ポリゴンの法線を計算する。
        // 続いて、前のサンプルでもあった「ポリゴン法線」の計算です。
        float3 vec1 = input[1].vertex - input[0].vertex;
        float3 vec2 = input[2].vertex - input[0].vertex;
        float3 normal = normalize(cross(vec1, vec2));

        fixed destruction = _Destruction;

        fixed r = 2.0 * (rand(center.xy) - 0.5);
        fixed3 r3 = r.xxx;
        float3 up = float3(0, 1, 0);

        // コードをループじゃない状態に展開することを明示する(詳細は下の記事を参照)
        [unroll]
        for (int i = 0; i < 3; i++)
        {
            appdata_t v = input[i];
            g2f o;

            UNITY_SETUP_INSTANCE_ID(v);
            UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);

            // 以下では、各要素(位置、回転、スケール)に対して係数に応じて変化を与えます。

            // center位置を起点にスケールを変化させます。
            v.vertex.xyz = (v.vertex.xyz - center) * (1.0 - destruction * _ScaleFactor) + center + (up * _UpFactor);

            // center位置を起点に、乱数を用いて回転を変化させます。
						float angle = rand((float)v.vid) * destruction * _RotationFactor * _Time.x*10;
						//X軸の回転行列
            float3x3 rotate = float3x3(1,0,0,0,cos(angle),-sin(angle),0,sin(angle),cos(angle));
            v.vertex.xyz = mul(rotate,(v.vertex.xyz - center)) + center;

            // 法線方向に位置を変化させます
            v.vertex.xyz += normal * destruction * _PositionFactor * r3;

            // 最後に、修正した頂点位置を射影変換しレンダリング用に変換します。
            o.vertex = UnityObjectToClipPos(v.vertex);

            o.color = v.color;
            o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);

            stream.Append(o);
        }
        stream.RestartStrip();
      }

      fixed4 frag(g2f i) : SV_Target{
        fixed4 color = tex2D(_MainTex, i.texcoord);
        return color;
      }

      ENDCG
    }
  }
}