🌈

そろそろShaderをやるパート14 カメラとの距離を測って使う

2020/11/07に公開

そろそろShaderをやります

そろそろShaderをやります。そろそろShaderをやりたいからです。
パート100までダラダラ頑張ります。10年かかってもいいのでやります。
100記事分くらい学べば私レベルの初心者でもまあまあ理解できるかなと思っています。

という感じでやってます。

※初心者がメモレベルで記録するので
 技術記事としてはお力になれないかもしれません。

下準備

下記参考
そろそろShaderをやるパート1 Unite 2017の動画を見る(基礎知識~フラグメントシェーダーで色を変える)

デモ

カメラとの距離に応じてカラフルなキューブの透明度が変わります。

Shaderサンプル

Shader "Custom/UseCameraDistance"
{
    Properties
    {
        //テクスチャー(オフセットの設定なし)
        [NoScaleOffset] _NearTex ("NearTexture", 2D) = "white" {}
        //テクスチャー(オフセットの設定なし)
        [NoScaleOffset] _FarTex ("FarTexture", 2D) = "white" {}
    }
    SubShader
    {
        //透明度に関する設定
        Tags { "RenderType"="Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            //変数の宣言
            sampler2D _NearTex;
            sampler2D _FarTex;

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

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 worldPos : WORLD_POS;
                float2 uv : TEXCOORD0;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.uv = v.uv;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex); //ローカル座標系をワールド座標系に変換
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                //それぞれのテクスチャとUVからピクセルの色を計算
                float4 nearCol = tex2D(_NearTex,i.uv);
                float4 farCol = tex2D(_FarTex,i.uv);

                // カメラとオブジェクトの距離(長さ)を取得
                // _WorldSpaceCameraPos:定義済の値 ワールド座標系のカメラの位置
                float cameraToObjLength = length(_WorldSpaceCameraPos - i.worldPos);
                // Lerpを使って色を変化 補間値に"カメラとオブジェクトの距離"を使用
                fixed4 col = fixed4(lerp(nearCol, farCol, cameraToObjLength * 0.05));
                //Alphaが0以下なら描画しない
                clip(col);
                //最終的なピクセルの色を返す
                return col;
            }
            ENDCG
        }
    }
}

・カメラとの距離が遠ければ遠いほど透明なテクスチャーを描画する割合増
・カメラとの距離が近ければ近いほどカラフルなテクスチャーを描画する割合増
という処理で成り立っています。

_WorldSpaceCameraPos

カメラのワールド座標を取得できます。
下記に定義済みの値は載っているようです。(教えてくださった方、感謝です)
【参考リンク】:Built-in shader variables

length

単純に引数の値(ベクトル)の長さの絶対値をfloatで返してくれます。
今回の使い方の場合、distance(a, b)と同じです。
むしろdistanceの方が早いっぽいです。今回は学習のために使用してみただけです。

ベクトルが2つの時はdistance、1つの時はlengthってことでしょう。

参考リンク

【Unity】カメラが近づくと弾けるポリゴン分解シェーダー
Unityシェーダプログラム入門 UnlitShaderの要素を全て解説
[Unity] シェーダで使える定義済値
GLSLをHLSLに書き換える

Discussion