Help us understand the problem. What is going on with this article?

[Unity] Cgでのライティングについてメモ

More than 5 years have passed since last update.

定義済値や定義の意味など、Unityでよしなにやってくれている部分などを含めて単純なDiffuseライティングをやるメモ。

シンプルなコード例

簡単なライティングをするコード例。

SubShader {
    Tags {
        "RenderType"="Opaque"
        "LightMode"="ForwardBase"
    }
    LOD 200

    Pass {
        CGPROGRAM

        #pragma vertex vert
        #pragma fragment frag

        struct vertInput {
            float4 vertex    : SV_POSITION;
            float4 normal    : NORMAL;
            float2 texcoord  : TEXCOORD0;
            float2 texcoord2 : TEXCOORD1;
        };

        struct vert2frag {
            float4 position : POSITION;
            float2 uv       : TEXCOORD0;
            float2 uv2      : TEXCOORD1;
            float4 color    : COLOR0;
        };

        uniform sampler2D _MainTex;
        uniform sampler2D _NormalTex;
        uniform fixed4 _LightColor0;

        vert2frag vert(vertInput v) {
            vert2frag o;

            float4 wpos    = mul(UNITY_MATRIX_MVP, v.vertex);
            float4 wnormal = mul(v.normal, _World2Object);
            float  diffuse = max(0, dot(_WorldSpaceLightPos0, wnormal));

            o.position = wpos;
            o.color    = _LightColor0 * diffuse;

            return o;
        }

        float4 frag(vert2frag i) : COLOR {
            return i.color;
        }

        ENDCG
    }
} 

ライティングの準備

  • "LightMode"="ForwardBase"タグをつける

これを付けないとライティングに関する情報が取得できません。

  • uniform fixed4 _LightColor0を宣言

uniform変数として、fixed4型の_LightColor0という変数を宣言します。
ここに、ライトの色が渡されます。

頂点シェーダで計算

頂点シェーダは以下のようになっています。

vert2frag vert(vertInput v) {
    vert2frag o;

    float4 wpos    = mul(UNITY_MATRIX_MVP, v.vertex);
    float4 wnormal = mul(v.normal, _World2Object);
    float  diffuse = max(0, dot(_WorldSpaceLightPos0, wnormal));

    o.position = wpos;
    o.color    = _LightColor0 * diffuse;

    return o;
}
wnormalの計算時、normalizeしてしまっていたので削除しました。normalizeするとうまく動きません。

処理としては法線をワールド空間座標に変換したのちに、ライトの位置との内積を取っています。
_WorldSpaceLightPos0はひとつ目のライトの位置です。これは自動的に宣言されているのでそのまま利用することが出来ます。

ちなみにUnityでは、DirectionalLightも視覚的に位置が表示されますが、実際には回転が影響を与えます。(当たり前ですが)
視覚的に見えている分、おや?となってしまうので勘違いしないようにしましょうw

法線の計算

法線の計算については、ワールド空間座標への変換を行っていますが、変換には若干の注意が必要です。
こちらの記事がとても参考になりました)

結論だけ言うと、 モデル行列の逆転置行列を掛ける 必要があります。
が、そこは少しだけ楽をして、Unityから渡されるモデル行列の逆行列(_World2Object)を、ベクトルに対して逆から掛けてやることで結果的に逆転置行列を掛けたことにしています。

色の計算

あとは、ライトの色と法線とライト位置から求めた内積を掛けあわせて最終的な色を決定している、というわけです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした