みつまめ杏仁

アンリアルエンジン(UE4)でGUIを作るためにゴニョゴニョしてます。UIデザイナーの皆様の助けになれば幸いです。

ゲージをテクスチャで増減させる

円グラフのように増減するゲージを作るとき、atan2(アークタンジェント2というプログラムの関数)をありがたく使わせてもらっています。少ないノードで実現できてしまうので、大変便利でありがたい存在。解像度に依存しないのもうれしい。ゲームで印象に残っているのはピクミン(2001年)かな。

原理的にはシンプルで、指定した座標と原点(0, 0)との位置関係を 角度 に変換してくれるというものです。なのでUV座標と atan2関数 を組合わせると下図のように変換することができます。

 

さらに Step や SmoothStepノードをつなげば円グラフゲージの増減が可能です。

 

アンリアルエンジンのマテリアルには ArcTangent2 というノードが用意されています。

そして便利すぎるのが VectorToRadialValue ノード。

このノードの中身を一部抜き出して整理するとこんな感じになっていました。


ただ、開発終盤の処理上げでこの atan2 が標的になることもしばしば。そこで前もって静的にテクスチャを作っておけばそれで対応できるんじゃないかということで、作ろうと思い立った次第です。

テクスチャのメモリ容量とその取扱いに対して atan2 の計算負荷、どちらが罪深いかはその時の描画面積やら描画状況次第ではあるので、どちらを採用するかは現場で判断することになります。

最初は作業時間優先で atan2 で作っておき、処理上げのタイミングで、テクスチャに差し替えたビルドと比較すると効果があるか、ないかが判明できると思います。

 

さてさて

Photoshopのグラデーションで、スタイルに 角度 というのがあります。

まさに atan2 を使ったような見た目のグラデーションが生成されます。

実際に使えるかどうか試してみたのが、Twitterに上げていた画像

ドキュメントのモードを RGBカラー と グレースケール 両方で試してみましたが、結果に目立つような差はありませんでした。

 

ということで、Processing を試すことにしました。。

最近だと SubstanceDesigner とかで作るのでしょうけど、AdobeCC の加入プランにラインナップされていないのもあって、昔お世話になった Processing を使うことにしたのです。

https://processing.org/

バージョンは 4になってました。

ジェネラティブアート界隈ではまだまだ活躍中で、コミュニティも多くそれなりに情報を拾うことができます。

この記事を書いているときもイベントが開催されていました。

Processing Community Japan

https://processing.jp/

 

マウスやキーの入力に反応することもできるので、インタラクティブな振る舞いも作って遊ぶことができます。

 

 

セットアップし、exeファイルを実行するとスケッチブックというエディタウィンドウが開くので、そこにスクリプトを書いていく。

言語は Javaをベースにしていて、JavaScriptに慣れていた自分としては、構文にすぐ馴染めるのでありがたい。

スクリプトを書くと、ウィンドウ左上の 再生ボタンをおすとすぐに結果が出る。

エラーがあれば、ウィンドウ下部のコンソールで教えてくれる。

無事エラーが出なければ、デスクトップにキャンバスウィンドウが新しく現れます。

 

void setup(){
  // キャンバスサイズ
  size(1024, 1024);
  // 背景色
  background(255,0,0);
  // 1回だけのDraw
  noLoop();
  // スムージング無効
  noSmooth();
}

void draw(){
  int dx = width / 2;
  int dy = height / 2;
  int x, y;  //描く座標
  float c;  //角度を明るさに
  //
  for(y=0; y < height; y++){
    for(x=0; x < width; x++){
      c = atan2(dy-y, x-dx) / PI// -1.0 ~ 1.0 にする
      c = c * 0.5 + 0.5;                 // 0 ~ 1.0 にする
      stroke(round(c*255));         // カラー
      point(x, y);                          // 点を描く
    }
  }
  save("image00.png");             // PNGでファイル書き出し
}

 

できました

描画し終えるとファイルに書き出すようにしています。

 

atan2 に座標を渡すときに、キャンバスサイズの半分の値を引くことで、0~1024だった座標の範囲を ±512 の範囲にずらしています。

上のサンプルでは、 X座標のところで、 x-dx としています。

これを dx-x に変えると UE5 と同じになります。

引き算の順番を変えると向きをコントロールできます。

あとからPhotoshopでテクスチャに書き出す際に回転すればいいだけなので、それほど気にする必要はないでしょう。ゲージの増減方向によって反転することもあります。

 

これをPhotoshopで開いて検証。

ヒストグラムもキレイ。うまく分布しているようなので安心。

できたPNGはサイズと向きを整えたらテクスチャに書き出してエンジンに持っていくだけなので、わざわざ グレースケールに変換する必要はないのだけど、一応グレースケールにしてみたら予想外の結果になった。グレースケールに変換した際に何らかのマッピング等補正が入るのかもしれない。

 

さっそくこのグラデーションを使ってゲージを作ってみた。

 

新たに以下のテクスチャを追加。サイズはどれも 64x64

グラデーションテクスチャは 256x256 にしました。

汎用という想定と、あまり小さいと、ドットのガビガビが目立つからです。

SmoothStepの扱いがちょっと雑ですが

残量によってカラーが変化するようにしています。

 

これに枠を重ねれば完成。

 

無事うまくいってよかった。

このリニアグラデーションテクスチャを使う方法は、いざ作るとなると手間ではあるけど、前もって作っておけば秘伝のタレのようにいつまでも使えるので、開発の初期や空き時間に用意しておくとよいかと。

 

シェーダーで atan2 を使う場合

  • 解像度を無視できるうえ精度が高い
  • 向きを変えるのはシェーダー内で
  • テクスチャが不要
  • 計算負荷が気になる

 

テクスチャを使う場合

  • 解像度に依存するので品質の制御が難しい
  • 向きを変えるのはテクスチャで
  • テクスチャメモリが気になる
  • 計算負荷が少ない

 

今回はこの辺で

ではではステキな円ゲージライフを!

 

 

最後におまけ

これも Processing で作れます。

距離を計算してくれる dist() という関数が用意されています。