知識0からのUnityShader勉強

知識0からのUnityShader勉強

UnityのShaderをメインとして、0から学んでいくブログです。

【UnityShader】オブジェクトにテクスチャを貼る #9

前回の成果

soramamenatan.hatenablog.com

リムライティングができるようになった。


今回やること

nn-hokuson.hatenablog.com

今回はオブジェクトにテクスチャを貼ります。

準備

f:id:soramamenatan:20190625173258p:plain

上の図のように、SceneにCubeを置いて、今回制作したMaterialをAttachしてください。



ソースコード

Shader "Custom/texture" {
    Properties {
        _MainTex("Texture", 2D) = "white" {}
    }
    SubShader {
        Tags { "RenderType" = "Opaque"}
        LOD 200

        CGPROGRAM
        #pragma surface  surf Standard fullforwardshadows
        #pragma target 3.0

        struct Input {
            float2 uv_MainTex;
        };

        sampler2D _MainTex;

        void surf(Input IN, inout SurfaceOutputStandard o) {
            o.Albedo = tex2D(_MainTex, IN.uv_MainTex);
        }
        ENDCG
    }
    FallBack "Diffuse"
}

やっていることはベースカラーを変えているだけですが、tex2Dが不明です。


まずは以前紹介しきれなかった#pragmaの他の機能について説明します。

fullforwardshadows

このディレクティブは影やテッセレーションを制御するためのものです。

ディレクティブ名 用途
addshadow 頂点シェーダーでモデルの形を変化させた時の影の位置を正しい位置にする
fullforwardshadows ポイントライトやスポットライト ※指定しないとデフォルトで設定されている
tessellate:TessFunction テッセレーション

今回の内容とあまり関係ないので、詳しく紹介してあるサイト様のリンクを貼っておきます。

addshadow

teratail.com

sleepygamersmemo.blogspot.com

fullforwardshadows

www.atmarkit.co.jp

tessellate:TessFunction

テッセレーションとは、ポリゴンをより細かく分割する手法のことです。

docs.unity3d.com

esprog.hatenablog.com

今回はfullforwardshadowsを明示的に記述しなくても大丈夫ですが、

#pragma surface  surf Standard

は定義しておかないとエラーになってしまいます。

Albedoにテクスチャの情報を代入する

サーフェスシェーダーは、1ピクセル毎にsurfメソッドが実行されるため、現在処理しているテクスチャの位置を知っている必要があります。

sampler2D

テクスチャをシェーダー内で使用するためには、sampler2D型の変数が必要となります。
なので、

sampler2D _MainTex;

この変数を定義しています。

uv_MainTex

struct Input {
    float2 uv_MainTex;
};

こちらはテクスチャの座標を表しています。
今回の場合ですと、Propertyから入ってくる_MainTexのUV座標が自動的に代入されます。
UV座標とは、オブジェクトの頂点座標にテクスチャのどの部分を描画するかを0〜1の間の値で示したものとなります。

tex2D

void surf(Input IN, inout SurfaceOutputStandard o) {
    o.Albedo = tex2D(_MainTex, IN.uv_MainTex);
}

UV座標(uv_MainTex)からテクスチャ(_MainTex)のピクセルの色を計算して返す関数となります。
ですので、Albedoの中にテクスチャの色が入ります。


こちらのサイト様を参考にさせていただきました。 www.atmarkit.co.jp

qiita.com

inspectorにテクスチャを入れる

f:id:soramamenatan:20190625191417p:plain

マテリアルに適当なtexture入れます。

f:id:soramamenatan:20190625191522p:plain

結果

f:id:soramamenatan:20190626151003p:plain

あれ、なんか逆になってる。。。面によっては正しい面もあります。

f:id:soramamenatan:20190626151213p:plain

どうして逆になるのか

3DグラフィックにはUVマッピングというものがあります。
これは、UV座標系を使用し、テクスチャをマッピングするものです。
これらはMayaやBlenderといったモデリングツールで設定されており、Unity側でUVを編集する方法はおそらくないです。
と書かれています。

answers.unity.com

じゃあどうするの?

アタッチしたマテリアルのTilingのX、Yの値を-1にします。

f:id:soramamenatan:20190626174856p:plain

そうすることで描画が逆となります。

f:id:soramamenatan:20190626174840p:plain

この方法はかなりゴリ押しなので、ちゃんとやるなら1から自分でtextureを生成した方が良さそうですね。


ソースコードにコメントを付与

Shader "Custom/texture" {
    // プロパティ
    Properties {
        // テクスチャのデータ
        _MainTex("Texture", 2D) = "white" {}
    }
    // あとで理解する
    SubShader {
        // 一般的なシェーダーを使用
        Tags { "RenderType" = "Opaque"}
        // しきい値
        LOD 200

        // あとで理解する
        CGPROGRAM
        // フォワードレンダリング
        #pragma surface  surf Standard fullforwardshadows
        // あとで理解する
        #pragma target 3.0

        // inpur構造体
        struct Input {
            // テクスチャのデータ
            float2 uv_MainTex;
        };

        // テクスチャのデータ
        sampler2D _MainTex;

        // surf関数
        void surf(Input IN, inout SurfaceOutputStandard o) {
            // テクスチャのピクセルの色を返す
            o.Albedo = tex2D(_MainTex, IN.uv_MainTex);
        }
        // あとで理解する
        ENDCG
    }
    // あとで理解する
    FallBack "Diffuse"
}

今回はこれで終わりです!
ここまで見ていただきありがとうございます!