先日、極座標のマテリアル構成について記事にしました。
その中でタンジェントの逆三角関数であるアークタンジェントとFracを使ってUVを極座標展開している部分について補足したいと思います。
続きを読むマテリアルでテクスチャのUVを極座標に変形すると、UVに切れ目が入るのですが、今まで良い回避方法が分からず困っていました。
以前、けだまじごく (@kedamazigoku) さんも呟かれていたこちらの現象です。
あとParagonに極座標UVのテクスチャフェッチしてるデータがあると聞いたので、高MipMap問題をどうやって解決してるか確認したら、対策してないものもあったし、NoMipMapにして対策してるものもあった。対策するかしないかの基準はよくわからん。 pic.twitter.com/sm6kE8eR3P
— けだまじごく (@kedamazigoku) May 17, 2018
テクスチャをNomipmapに設定すれば一応の回避はできますが、画面に小さくしか表示されなくても最大サイズのテクスチャが読まれてメモリを圧迫してしまうため、なるべくなら避けたいところです。。
そんな折、com04 (@com04) さんから対策案が‥!
UVが回るところでDDYの計算上出てしまうので元のUVで計算したらええんちゃうかな?的な。一応Mipmap使えるしそんなに差は分からないでしょー(アバウト pic.twitter.com/ltNm9PzQw6
— com04 (@com04) June 10, 2018
さらに、けだまじごくさんから追加情報が‥!
せっかくComputeMipLevelを使うのでしたら、極座標のUVをそのまま使って、ComputeMipLevelのMax処理(なぜかIfで書かれてる)をMinにして正攻法で攻めたほうが良いのかなと思いました。MinはMaxのときよりパフォーマンス不利ですが、Mipmapも考慮しつつアーティファクトがほぼ見えなくなります。 pic.twitter.com/5VdOh1kLWQ
— けだまじごく (@kedamazigoku) June 12, 2018
これは記事にして残しておかねば!‥ということでさっそく試してみました。
続きを読むUE4のマテリアルで距離に応じて色を変えたい場面があります。
例えばカメラに近付くと色が変わるとか透明になって消えるとか。
そんな時は「SphereMask」ノードを使うと便利です。
使い方としては例えばこのような感じ。
するとカメラから半径200以内に入ると白くなります。
黒から白への遷移はHardnessで調整します。
この時のRadiusとHardnessの関係をイメージにすると下図のような感じです。
HLSLのコードの中身までは見てないので違うかも知れません。。
今回の例の場合だと、カメラからの距離(つまり半径)以内に対象が入ると 1 を出力し(白くなる)、外なら 0 を出力する(黒くなる)という感じです。
Hardnessは 0 から 1 に遷移する長さという感じで、1 にすると即値が変わりますが 0 にするとカメラの位置までかけて緩やかなグラデーションが付きます。
プロジェクトで運用する場合、Hardnessのパラメータを外部に出す際にはSoftnessにでも名前を変えて「1-x」ノードを挟んで0~1の入力を逆転させた方が直感的でユーザーフレンドリーになる気はします。
エフェクトでの使用例で言えば、パーティクルがカメラに近付いた際に突き刺さらないよう消えるようにしたりは定番と思いますが、World position OffsetとParticleSizeノードを併用してカメラに近付いたパーティクルのサイズを小さくしたりとかもできそうです。
この時、ピクセル単位ではなくパーティクル全体に影響するので良ければSphereMaskのAに入力するのはParticlePositionノードが良いかと思います。
ちなみに、遠くと近くでテクスチャのタイリングを変えたい場合にSphereMaskでUVを直接ブレンドすると中途半端な数値になるのでUVの切れ目が見えてしまうので、UVをテクスチャに接続してからテクスチャ同士をブレンドすれば回避できます。
マテリアルを作成したり中身を解析したりしている時に、値の変動を脳内では処理できず紙に手描きでグラフを書くことがよくあるのですが、「値をグラフにするノードは無いものか」と思っていたところ hirapotさん(@hirappot)から「PlotFunctionOnGraph」というマテリアル関数を教えて頂きました!
hirapotさんありがとうございます!
ということで早速使ってみました。各Inputの説明は図に記述しています。
(Inputピンの「f(x)」にはUV座標のUを与えてやる必要があるっぽいです)
するとこのような結果に!これぞ求めていたものです‥素敵!
ちなみに中身を見てみたらこんな感じで把握するのが大変だったので‥
とりあえず最小限の構成に整理してみました。
グラフのVと入力した値のUの距離(Distance)が 0(つまり一致する位置)に色が付くようになっているようです。
ただ注意がひとつあって、Inputでグラフの座標の範囲を指定しますが、その範囲をグラフ化したい値にも反映させないとグラフと値が一致しません。
そのため、グラフのVとTimeを足し合わせた結果を出力するようにしました。
なので下図のように出力した値を使った値を入力する必要があって、ループした見た目の気持ち悪い構成になっていますが‥ひとまずこちらでうまく動作しました。
こういう時、マテリアル関数をふたつに分割すると良いのでしょうけれど、まいっかと。
ちなみに、試しにグラフ化するのに利用したのはLinearSine関数です。
このマテリアル関数は3つのOutputピンから三角波や矩形波を出力します。
1つめのOutputのLinearSineをグラフ化すると三角波になっているのが確認できます。
ついでに2つめのOutputのRounded Linear Sineも試してみます。
するとこんな感じ。
Debugノードで数値化はできますが、緩急はビジュアル化しないと分からないですよね。
3つめのOutputのDirectionも試してみます。
こちらは矩形波だということが確認できました。
という訳で、グラフ化でした。お試しあれ!
何か間違っていたりもっと良い方法があったりしたら教えてください‥!
(customノードで直接描画するようにした方が綺麗なグラフにできますかね‥)
UE4のマテリアルで、テクスチャのRGBAのどのチャンネルを使うかをマテリアルインスタンスで指定したい場合があります。
そんな時、Static Component Mask Parameterを使った場合はこちらのように構成すると‥
マテリアルインスタンスでチェックボックスを変えることで自由に指定できます。
しかしStatic Switch Parameterを使った場合と同様に、チェックボックスを変更すると別シェーダーとなり親マテリアルと同じデータサイズになってしまうという注意点があります。
この問題についてはEpic Games Japan篠山さんのスライドが詳しいです。
この問題を把握している上でStatic Component Mask Parameterを使用する分には良いと思いますが、代替えに良い方法があります。
それはDotproduct(内積)ノードを使う方法です。
テクスチャとConstantノードをDotで掛け合わせるだけです。
この時、テクスチャとConstantノードはチャンネル(要素)の数を合わせておきます。
Dotでどのような計算が行われているかというと、テクスチャのRとConstant 4VectorのRを乗算、GとGを乗算、BとBを乗算、AとAを乗算、それらを全て足す‥という感じです。下図のConstantノードはR以外0が入っているのでR同士の乗算の結果だけが残るという訳です。
そしてConstantノードをパラメータ化することで、マテリアルインスタンスで自由にチャンネルを指定することができます。内積がこんなところでも役に立つとは!
こちらのテクニックはUE4標準のNormalFromHeightmap関数で使われています。
以上、知っておくと便利と思う小技でした!
ガンマの検証とか、単純にテクスチャとして使いたいといった理由で、1ピクセルごとに色の値が1ずつ増える「256 pixel 256 諧調」の完璧なリニアグラデーション画像を作成したいことってないですか? 私はあります。
PhotoshopやSubstance DesignerやNukeなどでグラデーションを作成しても256pixelに256段階で推移しているのか確認すること自体が困難です。手作業で1ピクセルずつ塗っていく訳にもいきません。
ということでツールを作りました。
GitHubはこちら。Zipファイルはこちら。ライセンスはMITです。
2018.5/13(ver.2)
ボタンのサムネイルのグラデーションが間違っていたので修正
C# で作ったWindowsアプリが増えてきたので目次にしておきます。
全て「MIT Lisence」です。
リスク管理がしっかりしてる会社さんほど、ネット上にあるフリーソフトを気軽に使えないかと思います。商用利用でのライセンスを調べるために申請が必要だったり。
そしてライセンスの記載が無いと使用が難しくなったりするかと思います。
下記のツールは商用での使用はもちろん、改変・複製・再配布すべて自由です。
ソースまるごと公開しているツールだけGitHubにあります。
アーティストやゲームデザイナーの方はGitHubは見慣れないかも知れませんが、実行ファイルはTOP階層に置いている「binary」フォルダ内にあるので、拡張子が「exe」のファイルを選択して、飛んだページ先のDownloadボタンを押せばダウンロードできます。
■ 「Make File List」ファイルパス・フォルダパスをリストアップするツール
■ 「Folder List」サブフォルダをリストアップするツール
■ 「Folder Size Check」サブフォルダの総サイズのリストアップ(ListBox編)
■ 「Folder Size Check」サブフォルダの総サイズのリストアップ(DataGridView編)
■ 「List Fusen」リスト管理できるテキストエディタ
■ 「List Fusen 2」リスト管理できるテキストエディタのVer.2
■ 「Text Memory Tool」よく使う文字列をコピペするための補助ツール
■ 「Color Check Tool」BMP画像に保存された色の値を調べるツール
■ 「Make Linear Gradient 256」線グラデーション画像を作成するツール
■ 「Naming Check」UE4のアセットの命名規則チェックツール
◆便利ツール
・タスク管理ツール
シンプルなタスク管理ツール
最終的にはドットキャラがレベルアップするようなおまけの仕組みを入れたい
・twitterクライアント
過去のツイートを整理したいのでリツイート解除とコメント削除に特化したもの
・twitterのモーメント登録&管理ツール
モーメント関連のAPIが用意されていない?
少し調べてみたものの、しばらく様子見で‥
◆ファイル操作関連
・複数ファイルに対するリネームツール
正規表現、タイムスタンプ編集、個人情報削除
・複数テキストファイルに対する一括検索ツール
正規表現での検索と置換
・空フォルダ削除
・テキストのBOMあり/なし一括変換
◆画像関連
・画像簡易編集ツール
画像のコピペ、リサイズ、トリミングだけできれば良い
・画像ビューア
・FBXビューア
・簡易モデルに画像を貼り付けてプレビューするツール
・動画再生ツール
少し調べてみた感じやりたいことをやるには
日本語情報が皆無な感じのライブラリを使う必要がありそう
・デスクトップ画像キャプチャ
・デスクトップ動画キャプチャ
ガンマの理解のためにも、実際に画像に保存される色の値を調べたい時があります。
先日「Photoshopでリニアな状態で作業する」という記事を書いた後に気になったので、こちらのサイトの解説を参考に、Photoshopで保存したBMPの中身をバイナリエディタ「Stirling」で調べてみました。
それから、ウェブ上で2進法を10進法に変換してくれるサイトはこちら。
実際にPhotoshopで50%グレーの画像を作成し、作業用スペースをsRGBに設定した状態のものとLinearに設定した状態のものとをそれぞれBMPで保存。
「Stirling」で開いてみると、どちらのBMPも「7F」で埋め尽くされています。
この7Fが色の値ですが16進数なので10進数に変換します。
先ほどのサイトで調べてみると「127」と分かりました。
ちゃんと中間グレーの値がそのまま保存されています。
また、バイナリエディタで確認した2つの画像の中身はヘッダ情報も含め完全に一致しており、Photoshop(CS6)からBMP保存時にはカラープロファイル情報のチェックボックスがグレーアウトしますが、これで実際に保存されていないことが確認できたのではないかと思います。
※1:ググってみて出てきた記事によると、BMPには一応カラープロファイルを埋め込める仕様になっているそうですが対応しているアプリケーションはほとんどないとのこと
※2:PhotoshopからだとPSDは当然ですが、JPEGも保存時にカラープロファイルを埋め込めるようで、Photoshopで開くと保存前と同じカラー設定が適用されますが「Stirling」で調べるとsRGBで保存したファイルとリニアで保存したファイルの差異が激しかったのでそっ閉じしました
つまりPhotoshop上でどのカラースペースで作業しても、ディスプレイへの出力結果が変わるだけで、画像自体の色の値には影響が無いことが分かります。
自分は最近までこのあたりモヤモヤしていたのですがこれでスッキリしました。
ついでに、画像の色の値を調べるツールをC#で作ってみました。
制作時間はデバッグ含め2時間くらい。
放り込んだ画像サイズに合わせてレイアウトを崩さず丁度良いウィンドウサイズに広げるのに少し手間取りました。。ソリューション一式をGitHubにアップしています。
GitHubはこちら。Zipファイルはこちら。ライセンスはMITです。
大きな枠内に画像をドラッグ&ドロップして放り込んだ後、画像内をクリックすると「画像ファイルに保存されている色の値」をツール右側に表示します。
※追記:PictureBox内で補間の入る拡大縮小をしたりなど加工していなければ画像に保存された値と同じ値が取得できているは思うのですが‥このあたり何か判明したらまた追記したいと思います
ツール上での表示自体はsRGBになっているのではないかなと。。
そして中間グレーのBMPファイルを作業用スペースがsRGBの状態で保存したものとリニアのものと放り込んで色の値を見てみたところ、どちらも「127」であることが確認できました。
ちなみに前の記事のスナップショット画像を放り込んで左のsRGBのファイルの色の値を出してみると、127 ではなく 125 と出ました。JPEGでもBMPでも同様でした。
Photoshopの画面のスクリーンショットを取ってPhotoshopで貼り付けて保存すると色の値が少し下がる?(真っ白の場合は 255 → 254 になりました)
以前からガンマについて検証する際に画像をスクリーンショットで保存したりブラウザで表示することに正確性があるのか色々と不安がありましたが、ガンマ2.2かリニアかが比較できれば良いと思うので気にするほどではないですかね。。
前回の記事に引き続いて「割合」についてさらに書いておきたいと思います。
前回は「割り算が苦手」という話をしましたが、数学を苦手に感じる大きな要素の1つが割り算ではないかなと思っていて、学習に際しては割り算への苦手意識を減らすことが重要だと考えています。
そして「割合」もまた、割り算に大きく関係します。
とても分かりやすい表の入った算数プリントが「ちびむすドリル【小学生】」というサイトで無料配布されていましたので、引用させて頂きたいと思います。
日常生活では100%のように百分率を使うことが多いですが、数学やシェーダーの計算で百分率を使う場面はほとんど無いように思います。その代わりに「 1 を100%の値とした割合」をよく使う印象です。
「1 なら 100%」「0.5 なら 50%」「0 なら 0%」といった感じです。
PhotoshopのRカラー(8bit)の値は「0~255」なのはアーティストには馴染み深いですが、シェーダー等での色の計算は黒~白の範囲を「0~1」で表したりします。
UV座標も基本となる範囲は「0~1」で表しますし、「0~1」で表すことで「0.5なら半分の値」だし「2なら2倍の値」という風に、人間から見ても直感的でとても分かりやすく頭の中で計算もしやすくなりますね。
例えば 5 リットルのペットボトルに 3 リットルの水が入っていれば「全部で 5 ある内の 3 」つまり「」なので、「 3 ÷ 5 = 0.6 」になり、ペットボトルに対して水の割合が 0.6 ‥百分率で言えば 60% であることが分かります。
割合は、何かの値に対して掛けると「その値に対しての割合の値」が出ます。
何かを半分(50%)にしたかったら 0.5 を掛けますよね。
30に対して 0.5 を掛けると 15 が出ますが、これは30の半分は15であるということです。
「割合そのもの」は具体的な値(cmとかkgとか分のような)ではなく「何かに掛ける」ことでようやく「値」になります。
割合が 0.3 だったとして、この 0.3 は長さなのか重さなのか面積なのか分かりません。
ですが「60分」に対して掛ければ「18分」が出ます。
60 * 0.3 = 18(60分の30%は18分)
これは後に解説予定の「三角関数」で「cosやsinに斜辺の値を掛けると実際の長さが出る」ことを理解するために必要な考え方になるかと思います。
「1」は特別な数字だと思います。
割合での「1」は「100%」を表しますし、「1円」や「1時間」や「1cm」 や「1Kg」のような単位では「基準となる値」を表します。
これは結構大事なことだと思っていて「単位に定数を掛けたものが実際の値」という認識が必要な場面があると思うのです。
つまり単位が1cmなら「 1cm * 7 は 7cm」ということです。
例えば x,y 座標が ( 5, 3 ) だった場合は「xy座標の単位となる x=1,y=1 に対して 5 と 3 を掛けたものが現在の座標」と言い表すことができますよね。
「まだるっこしい考え方だなあ」と思うかも知れませんが、こちらも後に解説予定の「行列」が出てきた時に、必要になってくる考え方だと思います。
こちらの記事の例題が分かりやすいので引用させていただきます。
7cmで35gの棒は、15cmで何gになりますか
この場合まず「 1cm は何g か?」が分かれば計算が楽になるので、35g を 7 で割ります。
すると「 35 ÷ 7 = 5 」で「1cm は 5g」と1cm単位でのグラム数が出ます。
そしたら「1cm分のグラム数(5g) * 15cm = 75g」と計算しやすくなって答えが出ます。
こういった計算方法を「帰一法」というそうです(覚えなくて良いです)。
CGでは計算しやすくするためなんかに値を 0~1 に収めることを「正規化(Normalize)」と言いますが、MayaのUVエディタでUVを 0~1 の範囲にすっぽり収まるようスケーリングする際に、メニューから「正規化」を実行しますよね。
この正規化は帰一法と同じ考え方のようです。
他にも、シェーダーの計算でベクトルを正規化することがありますし、この数学シリーズでもベクトルと内積の解説の際に正規化が登場する予定です。
また、カラーとガンマの計算をする際には、RGB値を 0~255 の 8bit の単位ではなく 0~1 の正規化した単位に置き換えてから計算する必要があります。
例えば、RGBの値がPhotoshopで「37」の場合‥
0 から数えているので +1 して の状態ですよね。
すると割合は「0.1484375」で、正規化‥つまり「1が100%」の場合は割合である「0.1484375」がそのまま実際の値になります。
こちらを2.2乗したり0.4545乗したりしてガンマが絡む計算をすれば良い訳ですね。
という訳で「割合」とか「単位」とかの話でした。