気分転換にパネル表示をいじってみる。とりあえず半透明のパネルを出していたのだが、もう少し工夫したいのですりガラス処理+角丸四角形にしてみた。
中身のデザインが今ひとつだけど、とりあえずパネル自体はこんな感じかな。すりガラスも角丸もシェーダーで実装。
すりガラス
すりガラスは一般的にはガウシアンブラーを使うらしい。ただ、普通に5×5とかのカーネルで処理すると重くなるので、縦5をかけた後に横5をかける、みたいに2パスでやるらしい。検索するとそういう方針でGrabPass(レンダリングされた画像を取得するやつ)を使用した例がたくさん出てくる。
ただ、Universal Render PipelineだとGrabPassがサポートされてなくて、同様の機能を持つCameraOpaqueTextureを使うと2パスができない(と思う)。なので、カーネルを省略して十字みたいな感じに近似してみた。上の画像の通りそれっぽくはなるからいいかな。
角丸四角形
角丸四角形はなかなか難しい。公式的にはRounded Rectangleっぽいんだけどそのままコピペしてもうまくいかない。なので参考にしながら自力で実装。
float RoundedRectangle(float2 uv, float width, float height) { // uvは-width/2~width/2、-height/2~height/2の座標 // uvから一番近い矩形状の座標を計算する float2 pt = float2(min(abs(uv.x), width / 2 - _Radius), min(abs(uv.y), height / 2 - _Radius)); // 計算した矩形状の位置とuvとの差分ベクトルの長さを計算する float d = length(pt - abs(uv)); // 半径以内なら1、半径よりおおきければ0 return smoothstep(d - _Radius / 10, d + _Radius / 10, _Radius); } fixed4 frag(v2f i) : SV_Target { // 角丸四角形判定。範囲内にあるならr=1、ないならr=0 float width = 1 / _CameraOpaqueTexture_TexelSize.x; float height = 1 / _CameraOpaqueTexture_TexelSize.y; float2 uv = float2((i.uv.x - 0.5) * width, (i.uv.y - 0.5) * height); float r = RoundedRectangle(uv, width, height); // 角丸四角形外(rが0に近い)は描画しない。 clip(r - 0.1); ・・・ ガウシアンフィルタ処理(他でたくさん紹介されているので省略) ・・・ // 角丸のα値:r // オリジナルのα値:α // オリジナル色:o // ガウシアンフィルタをかけた背景色:b // とすると、以下で表せる // rα*o + (1-rα)*b fixed4 col = r * _Color.a * _Color + (1 - r * _Color.a) * b; return col; }
こういうときに数学が役立つ。数学の知識がない場合、ぴったりうまくいくコードを見つけてコピペするかAssetを買うしかないので不利になる。