UnityでCG Shaderを書いてみた

ChainZ(クリエイター)
いろいろやってます。

最近shaderの勉強を始めようと思って、ついでにUnityにも触ってみたいので、Unityでshaderを書いてみた。

shader言語の種類

1. Shaderlab

全てshader言語の基盤。

2. CG

Nvida社が開発した言語、勉強しやすい。今回はこれを使う!

3. GLSL

モバイル向け、CGとよく似てる。

実装の流れ

1.Unityでオブジェクトを作成

簡単なCubeにしよう(Create > Cube)。

2.テクスチャを作成し、Cubeに割り当てる

名前はmy_materialしとこう(Create > Material)。AssetsウィンドウでテクスチャをCubeにドラッグすれば割り当てられる。念のためInspectorウィンドウで確認しとこう。

3.shaderを作成

MyShaderというshaderファイルを作成する(Create > Shader)。shaderを使うには、先ほど作成したテクスチャを選んで、inspectorウィンドウでShaderを(Custom > MyShader)にする。

4.shaderを編集

MyShaderを開いく:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Shader "Custom/MyShader" {
  Properties {
      _MainTex ("Base (RGB)", 2D) = "white" {}
  }
  SubShader {
      Tags { "RenderType"="Opaque" }
      LOD 200
      
      CGPROGRAM
      #pragma surface surf Lambert

      sampler2D _MainTex;

      struct Input {
          float2 uv_MainTex;
      };

      void surf (Input IN, inout SurfaceOutput o) {
          half4 c = tex2D (_MainTex, IN.uv_MainTex);
          o.Albedo = c.rgb;
          o.Alpha = c.a;
      }
      ENDCG
  } 
  FallBack "Diffuse"
}

コードを下記のように整理しときます。

1
2
3
4
5
6
7
8
Shader "Custom/MyShader" {
  Properties {
  }
  SubShader {
      
  } 
  FallBack "Diffuse"
}

最初のShader "Custom/MyShader" {}はshaderの名前、変えてもオッケー。最後のFallBackは、もしshaderがうまくレンダリングされない時に、バックアップ用のシェーダなのだ。ここはデフォルトの”Diffuse”になる。

プロパティを追加

Colorプロパティを追加してみる。Propertiesの中に:

1
2
3
Properties {
  _Color ("Color", Color) = (1.0, 1.0, 1.0, 1.0)
}

と書くと、保存してUnityで見てみると、Cubeが紫になる。

これから色を変えられるようにしてみよう。 SubShaderの中に、Passブロックを追加

1
2
3
4
5
SubShader {
  Pass {

  }
}

CGを使うにはCGPROGRAMを明示しないといけない;

1
2
3
4
5
6
7
8
9
SubShader {
  Pass {
      CGPROGRAM
      
      //この間CGを書く
      
      ENDCG
  }
}

では、CGを書いてみる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
SubShader {

  Pass{

      CGPROGRAM

      // vertexシェーダ   => vert関数で返ってきた結果を受け取る
      // fragmentシェーダ => frag関数で返ってきた結果を受け取る
      // vert と frag は好き名前にしてもいいが、下記の関数名もそれに応じて変えてください。
      #pragma vertex vert
      #pragma fragment frag

      uniform float4 _Color;
      
      // 入力用構造体
      struct VertexInput{
          float4 vertex : POSITION;
      };

      // 出力用構造体
      struct VertexOutput{
          float4 pos : SV_POSITION;
      };

      // 出力用構造体を返す関数
      VertexOutput vert(VertexInput v)
      {
          VertexOutput o;
          o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
          return o;
      }

      // fragシェーダ
      // 選択した色を返す
      float4 frag(VertexOutput i) : COLOR
      {
          return _Color;
      }


      ENDCG
  }


} 

保存して、Unityでmy_materialの色を変えると、Cubeの色も変わる!