NinaLabo

個人ゲーム開発者の技術メモ

【memo5】シェーダーで step 関数を使ってみる(Unity)

【今日のまとめ】

・フラグメントシェーダーで if 文 は遅いらしい

・if 文 の代わりに step関数が使える。ただし、順序や不等号は要注意。

x >= edge x <= edge x > edge x < edge
step(edge,x) step(x,edge) 1.0 - step(edge,x) 1.0 - step(x,edge)

 

------------------------------------

Unity でゲームは作っていますが、Shader も 画像処理も初心者です。

アウトプットばかりだと腐っていくので、毎日1時間程度は自分の知らないことを少しずつインプットしていこうかと思ってます。

タイトルに【memo】とあるものはほぼ自分用の備忘録なので他の記事よりも殴り書きなのはご容赦ください。

------------------------------------

 

 

前回は下記資料を参考にdistance関数を使ってみました。

docs.google.com

 

今日のお題は黒い円です。写経だけだと頭を使わないので、そろそろ資料のコードをあまり見ずに作ってみようかと思います

 

*ドリル1: 黒い円 (Shader3Scene)

f:id:ninagreen:20180919192749p:plain

前回は下記の画像の状態ができたわけだけから、それを応用して距離が一定の閾値内は黒、それ以上は白にすればできそう

f:id:ninagreen:20180919193001p:plain

 

ってことでこれでいいんじゃない?

と思ったら、数字のfloatを表すfはいらないらしい

            float4 frag_test (v2f_img i) : SV_Target
            {
                float d = distance(float2(0.50.5), i.uv);
                return d > 0.5 ? 1f : 0f;
            }

 

こんな感じで、

            float4 frag_test (v2f_img i) : SV_Target
            {
                float d = distance(float2(0.50.5), i.uv);
                return d > 0.5 ? 1 : 0;
            }

こうなりました。簡単。シェーダーも三項演算子使えるんですね。

f:id:ninagreen:20180919193527p:plain

 

別にif文でもいいけどね、と思っていたら、どうもシェーダーだとif分は遅いとか?え・・・C#の世界では想像もつかない・・・

light11.hatenadiary.com

qiita.com

 

if文の代わりにstep関数を使うほうがいいらしい。

step (DirectX HLSL)

 

step(edge, value)

value が edge 以上の場合は1、それ以外は0

 

なので、先ほどのを書き換えるとこうですかね。

            float4 frag_test (v2f_img i) : SV_Target
            {
                float valuedistance(float2(0.50.5), i.uv);
                return 1 - step(value0.5);
            }

 

わかりにくい・・・

x < edge が step (x,edge) であるほうが個人的にはわかりやすいですが、逆なんですよね・・この対応表がわかりやすいですが、覚えられる自信がなく・・何回も調べてしまいそうです・・

 

x >= edge x <= edge x > edge x < edge
step(edge,x) step(x,edge) 1.0 - step(edge,x) 1.0 - step(x,edge)

 

 

短いですが、今日はここまで。