[ほぼ勉強内容のメモ] Shaderとは？（基礎中の基礎）

2022.6.13　

今日からUnityのShaderについて学んでいきます。
最終目標はスライムのようなぷよぷよとしたオブジェクトを制作することです。

## 参考資料
https://www.sejuku.net/blog/65234

## ShaderLab
シェーダーを書くには、ShaderLabというUnity上でシェーダーを記述する言語を使用するそうです。
言語の書き方自体もC＃などと大差がないため、覚えることは非常に少ないとか。。

## Shaderとは
Shader とは描画方法を記述したプログラムといえるそうです。

## Shaderを書く準備

### Shaderファイルを作ってみる
![bandicam 2022-06-13 18-20-14-248.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940156/165ee159-f138-3698-5b7a-2f932a110d54.jpeg)
![bandicam 2022-06-13 18-20-57-503.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940156/6b33d22c-a36b-4bb6-2b21-4fbca189429e.jpeg)
↑のように作成できます。

## 実際にShaderを書いてみる
最初なので、モデルを設定した色で表示するシェーダー処理を書いていきます。（書いたらMaterialを作成して、このShaderを設定→オブジェクトにつける）
（参考資料のコードまんまです＞＜ MyShaderの部分は自分がつけたShaderの名前に設定してください）

```C#
// シェーダーの情報
Shader "Unlit/MyShader"
{
    // Unity上でやり取りをするプロパティ情報
    // マテリアルのInspectorウィンドウ上に表示され、スクリプト上からも設定できる
    Properties
    {
        _Color ("Main Color", Color) = (1,1,1,1) // Color プロパティー (デフォルトは白)   a____
    }
    // サブシェーダー
    // シェーダーの主な処理はこの中に記述する
    // サブシェーダーは複数書くことも可能が、基本は一つ
    SubShader
    {
        // パス
        // 1つのオブジェクトの1度の描画で行う処理をここに書く
        // これも基本一つだが、複雑な描画をするときは複数書くことも可能
        Pass
        {
            CGPROGRAM   // プログラムを書き始めるという宣言
 
            // 関数宣言
            #pragma vertex vert    // "vert" 関数を頂点シェーダー使用する宣言
            #pragma fragment frag  // "frag" 関数をフラグメントシェーダーと使用する宣言
 
            // 変数宣言
            fixed4 _Color; // マテリアルからのカラー   a____
 
            // 頂点シェーダー
            float4 vert (float4 vertex : POSITION) : SV_POSITION
            {
                return UnityObjectToClipPos(vertex);
            }
 
            // フラグメントシェーダー
            fixed4 frag () : SV_Target
            {
                return _Color;   //a____
            }
 
            ENDCG   // プログラムを書き終わるという宣言
        }
    }
}
```

## プログラムの構成
重要な箇所は以下の5か所だそうです。
1.プロパティ情報
2.関数宣言
3.変数宣言
4.頂点シェーダー
5.フラグメントシェーダー
　
###　1.プロパティ情報
```C#
// Unity上でやり取りをするプロパティ情報
    // マテリアルのInspectorウィンドウ上に表示され、スクリプト上からも設定できる
    Properties
    {
        _Color("Main Color", Color) = (1,1,1,1) // Color プロパティー (デフォルトは白)   a____
    }
```
この「Propaties」で宣言されたブロックには、Unity側から送ってほしい情報を書くそうです。

ここに書いた内容は「シェーダーを持っているマテリアル」の「Inspectorウィンドウ上」に表示されています。![bandicam 2022-06-13 19-40-30-485.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1940156/444d30c6-8766-0c7f-04a4-b4c6fd5f6ce1.jpeg)

取得さえしてしまえば、あとはShader内の処理で好きに判定や繁栄を行えます。

### 2.関数宣言
```C#

            // 関数宣言
            #pragma vertex vert    // "vert" 関数を頂点シェーダー使用する宣言
            #pragma fragment frag  // "frag" 関数をフラグメントシェーダーと使用する宣言

```
一行目は、「頂点（vertex)シェーダーでは、vertという関数を呼び出してね」という意味。

二行目もほぼ同じ。

これを定義することによって、各シェーダー処理が実行っされるときに、自作した関数を呼び出してもらえます。

### 3.変数宣言
```C#
// 変数宣言
fixed4 _Color; // マテリアルからのカラー   a____
```
_colorという変数を準備しました。
先ほどのプロパティ情報箇所の指定によって、この変数にUnityから取得してきたデータが入ることになりました。

### 4.頂点シェーダー
```C#
// 頂点シェーダー
float4 vert(float4 vertex : POSITION) : SV_POSITION
{
      return UnityObjectToClipPos(vertex);
}
```
頂点情報を操作するshaderです。

### 5.フラグメントルシェーダー
```C#
// フラグメントシェーダー
fixed4 frag() : SV_Target
{
       return _Color;   //a____
}
```
ピクセル情報を操作するshaderです。

##　まとめ
・プロパティ情報・・・Unityから情報を取得するために定義
・関数宣言・・・シェーダー処理で、呼ぶ関数を指定
・変数宣言・・・「Unityからデータを受け取る」などの目的のため、変数を定義
・頂点シェーダー・・・頂点シェーダーの処理
・フラグメントシェーダー・・・フラグメントシェーダーの処理

流れとしては
①　変数宣言・プロパティ情報で、必要な情報を取得して、
②　関数宣言で指定した頂点シェーダー・フラグメントシェーダー関数で実際に行う処理を記述する

## なんかスライムっぽいものを作れそうなのでは！？というものを見つけた

https://techblog.kayac.com/unity_advent_calendar_2018_22

次は↑の資料を読んで実際に実装してみます。