ユニティちゃんで学習。座標を色に変換するUnity 3Dシェーダーの作り方。
スクリーン座標の分かり辛いz軸とw軸について。
関連ページ
参考URL
前回
はマテリアルに単色を代入するシェーダーを作りました。
今回はモデルの座標を無理やり色に変換するシェーダーを作っていきます。

テストに使う3Dモデル
3Dモデルは
SDユニティちゃん
を使っていきます。導入方法は
こちら
。

スクリーン座標を色に変換するシェーダー
頂点シェーダーで受け取った座標を、ピクセルシェーダーで色に変換するコードを書いていきます。
実用的ではないですが、シェーダーの仕組みを知るのに割と便利です。
以下コード全文です。今回のスクリプトで特徴的なところを青く塗ってあります。
Shader
"Unlit/CoordinatesColor"
{
SubShader
{
Pass
{
CGPROGRAM
#pragma
vertex
vert
#pragma
fragment
frag
//後述のComputeScreenPos関数に必要な宣言
#include "UnityCG.cginc"
struct
appdata
{
float4
vertex
:
POSITION;
};
struct
v2f
{
float4
vertex
:
SV_POSITION;
//スクリーン座標を保存してピクセルシェーダーに伝えるために追加
float4 screenPos : TEXCOORD0;
};
// 頂点シェーダー
v2f
vert
(appdata
v)
{
v2f
o;
// ワールド座標をカメラを原点とする座標系に変換し、
// かつカメラの画角外の頂点を削ります
o.vertex
=
UnityObjectToClipPos(v.vertex);
// クリップ座標を正規化してスクリーン座標に変換
o.screenPos = ComputeScreenPos(o.vertex);
return
o;
}
// ピクセルシェーダー
fixed4
frag
(v2f
i)
:
SV_Target
{
//座標情報を無理やり色に変換
//x軸をr(赤)に、y軸をg(緑)、z軸をb(青)に代入する
return fixed4(i.screenPos.x, i.screenPos.y, i.screenPos.z, 1);
}
ENDCG
}
}
}
後述しますが、
i.screenPos.z
の代入だけは実際はz軸の座標が関係ない処理になっています。
ユニティちゃんの服に使っている
def_mat
のシェーダーを、作成したシェーダーに変更します。
実装した結果は次のようなものになります。

スクリーン座標とは何か
Unityシェーダーで言う
スクリーン座標
とは、UnityC#でいうビューポート座標に近いです。
カメラの画角の左下をx=0, y=0として、右上をx=1, y=1とする、正規化された座標
の事を言います。
下の画像を見ての通り、x軸が右に寄るほど赤色が濃くなり、y軸が上に寄るほど緑色が強く出ています。
一方でビューポート座標とは手前と奥の座標の扱い方がかなり異なります。
ComputeScreenPosで得られたスクリーン座標は、z軸が常に0.5で意味のない値
になっています。
z軸の代わりに使うのがw軸の座標です。
スクリーン座標のw軸は、カメラの座標に近づくほど0に近づき、カメラから離れるほど1に近づきます
。
カメラのz軸座標と完全に重なったとき、このw軸は0になります。
またTransformのz軸の値が、カメラのz軸から+1になった段階で、このw軸は1になります。そこから1以上には増えません。
つまり先ほどピクセルシェーダー内のコードは、スクリーン座標のz軸を青色に代入しているので、実際には青色の値は常に0.5になっています。
// ピクセルシェーダー
fixed4
frag
(v2f
i)
:
SV_Target
{
//座標情報を無理やり色に変換
//x軸をr(赤)に、y軸をg(緑)、z軸をb(青)に代入する
return fixed4(i.screenPos.x, i.screenPos.y, i.screenPos.z, 1);
}
分かりやすく四角形で座標と色の関係をまとめると次の通りです。
0
0