液晶のピクセルをシェーダーで再現する
こんにちは!Ka-punnです!
シェーダーアドベントカレンダーに初めて参加します!
この記事は12月24日クリスマスイブの記事として書かれています!
https://qiita.com/advent-calendar/2019/shader-advent-calender-2019
前日は7CITさんによる
「マッハで学ぶ VRChat Shader LV5 習得 までのLV別 技術情報まとめ」でした
液晶画面っぽいシェーダー
今回の記事は自身のTwitterでもアップした
液晶画面のピクセルをシェーダーで再現するというものです
UE4でTVのピクセルのシェーダーテスト
— Ka-punn (@PunnKa) 2019年12月8日
入力したテクスチャーを完全にピクセル化して
スクリーン上に映っているっぽくできた
グラデーションがある画像でもちゃんとピクセル化されます
スターウォーズなのは特に意味はありません
バックが黒い画像にしたかっただけです#UE4 #UE4Study pic.twitter.com/YzuoPvO2nJ
特にこだわりがなければ普通にTextureにピクセルのマスクをかければいいですが
これでは入力したテクスチャーにただマスクが乗算されただけになっています
試しにこのシマウマ君を使ってやってみます
ちなみにこのシマウマ君は僕がデザインしたキャラです
よかったら見てみてくださいね
入力されたシマウマ君テクスチャーのRGBと下のようなピクセルの画像のRGBを
それぞれMultiplyしてチャンネルを統合します
拡大してみてみるとこんな感じです
もっと拡大して見てみるとピクセルの一部がべた塗ではないところが出てきています
ピクセルの配列と関係なくテクスチャーを乗算しているので当たり前ですね
これでも拡大して見なければそれっぽくはなりますしコストも安く済むはず・・
でもせっかくなのでもうちょっと凝ってみます
液晶モニターの仕組みを調べてみる
このようにピクセルのRGBの濃淡で描かれているので1つのピクセルにいろんな色が入ったり形が変わることはありません
https://av.watch.impress.co.jp/img/avw/docs/686/463/html/panap01.jpg.html
どんな画像でも寄りで見てみるとRGBの三色で描かれています
今回それを再現してみます
最終的な目標は
入力したテクスチャーを自動的にピクセル状にすること
RGBのピクセルの濃淡のみで絵を再構成する
ということをやってみたいと思います
入力した画像をピクセル状にするには
どうやったらできるだろうかと考えていたところ
SubstanceDesigner(以下SD)のFloodFillGrayScaleというノードからヒントを得ました
以前僕がTwitterで載せたSDのノードをUE4で再現するというものがあります
SubstanceDesignerのFloodFillGrayScaleの挙動をUE4で再現
— Ka-punn (@PunnKa) 2019年11月15日
入力したMaskの形に応じてブロックをマスクできます
使いどころはわからないけどこういう風に
パタパタ変わっていく感じが必要だったので検証#UE4 #MadeWithSubstance pic.twitter.com/cujtMihZpt
これは入力したマスクテクスチャーをブロック状に変換しています
この考え方を使えばできそうですね
このシェーダーはマスクとなるグレースケールのテクスチャーのほかに
FloodFillとよばれるテクスチャーを使用しています
FloodFillによってUVをいじってTwiterに投稿したような表現が可能になっています
その前にシェーダーアドベントカレンダーの2日目の
mokoさんによる「UE4講師付きモザイクマテリアル」を見てください
テクスチャーをピクセル状にするのと同じくこのようにモザイク状にするには
UVを各ブロックごとにフラットな数値が入っていればできるということがわかります
UVをRとGそれぞれ分けてみてみるとやはりタイリングさせた分だけ
0~1のUVが分割されU,V方向それぞれ 0,0.1,0.2,0.3,0.4・・という値でブロック状になっています
FloodFillテクスチャーとは
次にFloodFIllテクスチャーを見ていきます
SD内で簡単に作成することができます
各チャンネルごとに見ていきましょう
一番左の画像がFloodFillテクスチャーでその他右4つが各チャンネル成分です
左から3つ上から3つ目のグリッドを取り上げてみると数値は以下のようになっています
- UVの値は 0.3 ~ 0.4
- Rチャンネル 0.0 ~ 1.0
- Gチャンネル 0.0 ~ 1.0
- Bチャンネル 0.1 ~ 0.1
- Aチャンネル 0.1 ~ 0.1
計算方法は
RとBをかけると 0.0 ~ 0.1になります
それをUVの0.3 ~ 0.4から引くと0.3 ~ 0.3になります
またGとAをかけてUVから引くと同じく0.3 ~ 0.3となります
U方向はRに対してB
V方向はGに対してAになっています
この計算をUE4で再現すると
出力結果をみると溝にまで色が入っていますね
これをBかAチャンネルの値を使ってマスクしていきます
やり方は簡単でCeilを使って1してしまいます
それを最後にMultiplyすればOKです
しかし!これだとFloodFillをタイリングすることはできません
このような結果になってしまいます
ではタイリングできるようにするにはどうすればいいでしょうか
原因はBとAに入っている数値です
今回使用しているテクスチャーは10x10のグリッド上のものです
UとV方向に10分割されており1を10で割った0.1の値が入っています
それを上の写真のように元のUVに対して2をかけると20x20のグリッドになります
しかしBとAにおいてタイリング数は変わっていますが値は0.1のままです
そこでBとAの値をタイリングした分だけ割ってやるとうまくいきそうですね
DivideでTiling分を割ってやるとうまくいきました!
以上がFloodFillを使ったUVをピクセル状にする方法です
次から実際に作成していきます
UE4で組んでみる
ピクセルの元となるSDでのFloodFillテクスチャーの作り方ですがすごい簡単です
TileGeneratorでベースとなる形を作成しFloodFillにつなげるだけです
この際TileGeneratorの部分はほかの要素でも大丈夫です
3つのラインにしているのはテクスチャーの容量を最小限に抑えるためです
どのみち大量にタイリングしますのでテクスチャーサイズも512x512くらいでOKです
もっと小さくても大丈夫だと思います
ではUE4でのマテリアルを見ていきましょう
まずSDで作成したFloodFillのTextureをUE4にインポートします
今回Alphaチャンネルを個別にマスクとして使用しているので
textureの設定の部分の「sRGB」のチェックを外してください
続いて新規にマテリアルを作成しノードをつないでいきます
ノードの全体像はこちら
TilingとMake Flat UVの部分の拡大画像です
ここまでは上のほうに書いた方法と同じです
次にMake Flat UVで作ったUV情報をBaseColorのUVに入力します
そしてBaseColorのRGBをそれぞれSmoothStepでいじれるようにしておきます
しかしこのままだと溝部分にまで色が入っているので
最後にピクセルとなるテクスチャーを用意します
RGBをそれぞれかけてMakeFloat3にいれて合成し完成です!
PixelMaskの部分には同じTiling数をかけておきましょう
ただし前工程のTilingグループのようにDivideする必要はありません
完成!
おまけ
ピクセルの形をこのようにスマイリーにしても面白いですね
拡大して見るとこんな感じです
スマイリーの作り方はこんな感じ
では明日で最後のシェーダーアドベントカレンダーは
さやちゃんぐbotさんによる
「忙しい人のためのシェーダーアドベントカレンダー2019まとめ。」です!
ここまで読んでいただきありがとうございました!