切り絵が趣味の僕がプログラムや創作物について書き溜めるブログ

絵やモデリングやプログラミングなど僕が作った物について。アニメの感想や心動かされたきっかけなどを書き溜めるブログです。Boothで3Dアバターの販売もしていますhttps://paw.booth.pm/

【1日目】VRChat民のための少しづつ身に着けるシェーダー入門

こんぱう~~
VRchatでシェーダーに詳しい方から毎週土曜日の21:00~22:00の間に講義をしてもらうことが決まりました!!

初心者の僕に合わせてもらって基本的なことからゆっくりと教えてもらいます
なので、せっかく教わったことをまとめていこう~~~!っていうのがこの"少しづつ身に着けるシェーダー入門"というシリーズにしていこうと考えております

いままでに一度もプログラミングを書いたことがない人には少し難しいかもしれません... C言語でもなんでもいいので少しは触ったことがある。HelloWorldを表示させたことがある人なら大丈夫だと思います

 

今回教わったことは、

・シェーダーとは何なのか?

f:id:kiriesto:20210523080824j:plain
Unityで改変しているとなんとなく聞く言葉で、Toon LitとかUnitychan TOON Shader(UTS)、Matcapみたいなのがあるなぁという感じだと思います。

Toon Litだとアニメみたいな感じになって、Standardだと影がつくみたいな

まさにその通りで
「3Dオブジェクトをディスプレイにどんな感じに映し出すかを記したプログラム」です。

余談ですが、UnityのシェーダはShaderLabと呼ばれるUnity独自の記法で書かれているそうです。
参考:ShaderLab 構文 - Unity マニュアル

・型の宣言

型とはC言語でいうint、char、float、doubleの部分になります。int num;、char str; みたいに変数numはint型、変数strはchar型だよって宣言します。

宣言をしないと機械がコードを読もうとするときに「numって何??」ってなってしまうので、あらかじめ「numという箱には数字を入れます!!」って宣言することで機械がnumの中身を確認した時に「この箱の中身は数字!」と分かるようにします。

shaderでよく使う型の宣言が少し特殊だったので説明したいと思います。

floatとかfloat2、float4みたいに書きます。floatはC言語と同じ32bit浮動小数点値。
では、float2とfloat4にくっついている2と4は何なのか?

それはfloat2だとfloatの値が2個セット、
float4はfloatの値が4個セットという意味になります。

シェーダーは画像(画素)を扱うので、float2だとxy座標の値を入れたり、float4だとrgba(赤、緑、青、アルファ値)で色の情報を入れたりします。

最初はfloatの後ろに2、4がくっついてなんか変だな?って感じでしたが意味が分かるとなんだそんなことかーーって感じですね

・下準備

f:id:kiriesto:20210523111556p:plain
完成したシェーダーを実際に描画するために、上の画像みたいになるようにUnityを設定していきます。

まず、適当な画像を用意してAssetsに入れておきましょう
f:id:kiriesto:20210523111844p:plain
こんな感じになっていると思います。
(New Fol...、Scenesのフォルダはなくても問題ないです。今まで書いたシェーダーとかをしまっているだけです。)

次にprojectの中で右クリックをしてCriate->Materialを選択して、Materialを追加します。
f:id:kiriesto:20210523112328p:plain
Materialが追加されました。
f:id:kiriesto:20210523112427p:plain
Hierarchyの中で右クリックをして3D Object->planeを選択して、planeを追加します。 f:id:kiriesto:20210523123823p:plain
planeを選択した後に、Materialをplaneにドラック&ドロップしてください。
Inspectorのmaterialの名前が変更さえたらOKです。 f:id:kiriesto:20210523124752p:plain
Materialを選択して適当なテクスチャを矢印のところに入れてください f:id:kiriesto:20210523142624p:plain
できたら、planeの色がテクスチャの色になっていると思います。
f:id:kiriesto:20210523142958p:plain
これで下準備ができました。
では実際にシェーダーを書いていきましょう!!

・シェーダー作成する

Assetsで右クリックしてCreate->Shader->Unlit ShaderでShaderを追加しましょう
f:id:kiriesto:20210523144001p:plain
Standard Surface Shaderは描画を自動でしてくれる代わりに内容が複雑で改変しにくい
Unlit Shaderは描画処理を記述しなくてはいけないけど中身を改変しやすい

教えてくれる人がUnlit Shaderから始めましょう!!ってなったのでしばらくはUnlit Shaderからプログラミングします。

出来たシェーダーを右クリックしてShow in Explorerするとフォルダーが開くので適当なテキストエディターでシェーダーを開いてください。(僕はVScodeを愛用してます)
f:id:kiriesto:20210523145440p:plain
f:id:kiriesto:20210523151415p:plain
こんなコードが開けたらOKです。
さっそくコードを書いていきましょう。

・テクスチャを動かす

いまから挑戦するのはテクスチャの位置を動かすってことをします。

何も変更してないシェーダーを適用した場合は f:id:kiriesto:20210523152758p:plain
このようになります。

テクスチャ移動のシェーダーで描画すると右のScroll_X、Scroll_Yの値を変更すると左の画像の位置が動いているのがわかると思います。
f:id:kiriesto:20210523153401p:plain

・シェーダーを書く

一番下に今日作ったシェーダーを記述しておきます。
f:id:kiriesto:20210523160310p:plain
Properties{}はUnityから値を受け取るところになります。
SubShader{}内でUnityからの値を使用するために宣言しておきます。
f:id:kiriesto:20210523170428p:plain
54行目の i.uvにUVデータが入っているのでfloat2型にしたx座標とy座標の値を加算することでテクスチャの表示を動かすことができます。 f:id:kiriesto:20210523170950p:plain

出来たら保存して、MaterialにShaderをドロップ&ドラッグして適応すると更新できます。

以上で今日はここまで
いいゆめを~~~
(一番下にコードがあります。)

kiriesto.hatenablog.com

 

Shader "Unlit/New"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Scroll_X("Scroll_XX", float) = 0
        _Scroll_Y("Scroll_Y", float) = 0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _Scroll_X;
            float _Scroll_Y;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv + float2(_Scroll_X, _Scroll_Y) );
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}