Unity用、シェーダー内の数値を可視化するシェーダー。
(A shader to visualize variables in Unity shader)
関連ページ
参考URL
Shaderを開発する上で問題になるのが、Shader内ではログ出しが出来ないこと。
このためShader開発の始まりから終わりに至るまで開発者はコード内の変数の値を想像しながら作り切るしかない。
こういった問題を解決するため、Unity環境では既に有志の方が
Shader内変数を可視化するシェーダー
を作っている。
このシェーダーは充分な機能を備えてるが、3D Object上に表示する設計をしていて、ほぼuGUIしか使わない自分には少し使いづらかった。
勉強のためにもこれをuGUI用にカスタマイズ+αしたシェーダーを作ってみた。
数値可視化シェーダーの使い方
今回のシェーダーは特定の画像がセットで必要なので、画像とシェーダーとマテリアルをUnityPackageにまとめておいた。
こちらのアドレス
から取得できる。
落としたファイルをダブルクリックすると必要なファイルがImportされる。Project上はAssets直下に配置されるはず。
このシェーダーはuGUI Image用に作ってあるので、ImageコンポーネントのMaterial部分にImportしたマテリアルをアタッチして使う。
RectTransofmのWidthは500、Heightは50が推奨となってるが、目視できる大きさであれば何でも良い。
ImportされたDebugShader.shaderを開き、フラグメントシェーダーのnumの部分に数値を代入すると、それが画面上に可視化される。
注意点として、整数部分が大きすぎると、小数点以下の数値の精度が著しく落ちる。floatの性質上しょうがないかも。
コード全文と補足
一応コード全文もここに載せておく。
自分としては珍しく頂点シェーダーも弄っていて、スクリーン上に表示されるImageの横幅を操作してる。
Shader
"Test/DebugShader"
{
Properties
{
_MainTex
("Texture",
2D)
=
"white"
{}
_IntergerCount
("IntergerCount",
Range(1,
6))
=
6
_DecimalCount
("DecimalCount",
Range(0,
6))
=
6
}
SubShader
{
Tags
{
"Queue"
=
"Transparent"
}
Cull
Off
ZWrite
Off
Blend
SrcAlpha
OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma
vertex
vert
#pragma
fragment
frag
struct
appdata
{
fixed2
uv
:
TEXCOORD0;
fixed4
vertex
:
POSITION;
fixed4
color
:
COLOR;
};
struct
v2f
{
fixed2
uv
:
TEXCOORD0;
fixed4
vertex
:
POSITION;
fixed4
color
:
COLOR;
};
sampler2D
_MainTex;
int
_IntergerCount;
int
_DecimalCount;
//アタッチした画像の数字記号の桁数、0123456789+-.で全部で13桁
static
fixed
textureDigit
=
13;
//スクリーン上に表示されるImageのwidthを、数字一桁分のwidthに圧縮するために使う
static
fixed
toSoloWidth
=
12;
//スクリーン上に表示する数字と記号の桁数。符号、整数、小数点記号、小数点数に分かれる
fixed
viewDigitCount()
{
return
1
+
_IntergerCount
+
step(1,
_DecimalCount)
+
_DecimalCount;
}
v2f
vert
(appdata
v)
{
v2f
o;
//画像の横幅を数字一桁まで圧縮した上で、必要な数字の桁分まで広げる
fixed
soloWidth
=
v.vertex.x
/
toSoloWidth;
v.vertex.x
=
soloWidth
*
viewDigitCount();
o.vertex
=
UnityObjectToClipPos(v.vertex);
o.uv
=
v.uv;
o.color
=
v.color;
return
o;
}
//num = Textrue上の表示したい数字もしくは記号の座標、0~12までの可能性がある
//placeIdx = 表示したいスクリーン上の座標のidx, 一番左が0
fixed4
getNumber(v2f
i,
int
num,
int
placeIdx)
{
fixed
oneCellWidth
=
1
/
textureDigit
*
toSoloWidth
/
viewDigitCount();
//表示したい数字の座標にuvを修正
fixed2
fixUv;
fixUv.x
=
i.uv.x
+
num
*
oneCellWidth
-
placeIdx
*
oneCellWidth;
fixUv.x
=
fixUv.x
/
toSoloWidth
*
viewDigitCount();
fixUv.y
=
i.uv.y;
//対象の桁と関係ない部分は切り捨てて画像を返す
fixed
cutRight
=
step(i.uv.x,
oneCellWidth
+
placeIdx
*
oneCellWidth);
fixed
cutLeft
=
1
-
step(i.uv.x,
placeIdx
*
oneCellWidth);
fixed4
col
=
tex2D(_MainTex,
fixUv)
*
cutRight
*
cutLeft;
return
col;
}
//渡された数値の指定の桁の値を取得
int
getDigit(float
num,
float
digit)
{
return
(int)(abs(num)
*
digit)
%
10;
}
//指定の桁の整数の画像を取得
//addIdx = 大きいほど整数の桁が小さくなる
fixed4
getIntegerTextureNumber(v2f
i,
float
num,
int
baseIdx,
int
addIdx)
{
float
digit
=
pow(10,
-1
*
(_IntergerCount
-
addIdx
-
1));
int
digitNum
=
getDigit(num,
digit);
return
step(addIdx,
_IntergerCount
-
1)
*
getNumber(i,
digitNum,
baseIdx
+
addIdx);
}
//指定の桁の小数点数の画像を取得
//addIdx = 大きいほど小数点数の桁が小さくなる
fixed4
getDecimalTextureNumber(v2f
i,
float
num,
int
baseIdx,
int
addIdx)
{
float
digit
=
pow(10,
addIdx
+
1);
int
digitNum
=
getDigit(num,
digit);
return
step(addIdx,
_DecimalCount
-
1)
*
getNumber(i,
digitNum,
baseIdx
+
addIdx);
}
//渡した数字を画像に変換
fixed4
convertNumver(v2f
i,
float
num)
{
fixed4
col
=
0.0;
//最初に+か-の符号を描画
int
placeIdx
=
0;
fixed
isSignMinus
=
1
-
step(0,
num);
col
+=
getNumber(i,
10
+
isSignMinus,
placeIdx);
//整数部分を表示
placeIdx
+=
1;
for(int
cnt
=
0;
cnt
<
_IntergerCount;
cnt++)
{
col
+=
getIntegerTextureNumber(i,
num,
placeIdx,
cnt);
}
//小数点記号を表示
placeIdx
+=
_IntergerCount;
col
+=
step(1,
_DecimalCount)
*
getNumber(i,
12,
placeIdx);
//小数点数表示
placeIdx
+=
1;
//何故か小数点以下でfor文を使った計算を行うと大きく値がずれるので1つずつ実行
col
+=
getDecimalTextureNumber(i,
num,
placeIdx,
0);
col
+=
getDecimalTextureNumber(i,
num,
placeIdx,
1);
col
+=
getDecimalTextureNumber(i,
num,
placeIdx,
2);
col
+=
getDecimalTextureNumber(i,
num,
placeIdx,
3);
col
+=
getDecimalTextureNumber(i,
num,
placeIdx,
4);
col
+=
getDecimalTextureNumber(i,
num,
placeIdx,
5);
/*
for(int
cnt
=
0;
cnt
<
_DecimalCount;
cnt++)
{
col
+=
getDecimalTextureNumber(i,
num,
placeIdx,
cnt);
}
*/
return
col;
}
fixed4
frag
(v2f
i)
:
SV_Target
{
//整数値が大きいと小数点以下の数値が大きくバグる
float
num
=
_ScreenParams.x;
return
convertNumver(i,
num);
}
ENDCG
}
}
}
プロパティは2つ用意してある。
IntegerCountのスライダーを弄ることで、整数部分の数値の表示桁数を1~6の範囲で制御できる。
DecimalCountのスライダーを弄ることで、小数点数以下の数値の表示桁数を0~6の範囲で制御できる。
ただ作った後に気付いたが、全く無駄な機能で両方とも最大値の6固定で良いと思う。
1
1