読者コミュニティ|Unity ShaderGraph CookBook vol.1
本の感想や質問をお気軽にコメントしてください。
ツイッターでもいつも勉強させて頂いています。
本の内容を見ながらノードベースでシェーダーの基礎を学び、現在はプログラムでシェーダーを書く勉強をしています(ありがとうございます)。
質問なのですが、
本のツイートにリプライされていたこちらの液体を、シェーダーで再現しようと奮闘中です。
オブジェクトの動きに応じて、動的に変化するところに魅力を感じています。
考え方は「3Dオブジェクトの中に液体が入っているような感じにするシェーダーグラフ」の応用で、
csファイルでサイン波を制御しているのかな?と思っているのですが、
書き方がわからず、スクリプトをどこかで解説して頂けると嬉しいです。
気が向いた時によろしくお願いします!(質問が直接関係のない内容で申し訳ありません)
ShaderGraphでサイン波を表示させつつ、サイン波の振幅をCSスクリプトで変化させることで液体っぽく見せています。`
サンプル
サンプルデータをGitHubにアップしましたので、ご覧ください
Assets/_SampleData/ShaderSamples/13_Liquid
実装(C#スクリプト)
CSスクリプトの実装は以下のような感じです。
using UnityEngine;
public class Liquid : MonoBehaviour
{
[SerializeField] float maxWaveSize = 0.3f; // 波の高さ
[SerializeField] float k = 1f; // 数値を増やすほど波が速く減衰
[SerializeField] float waveSize = 0f;
[SerializeField] float waveSpeed = 0f;
[SerializeField] Vector3 waveDirection = new Vector3(1f, 0f, 0f); // 波の方向
[SerializeField] float waveSizeInfluenceByMove = 0.001f; // 移動が波の高さに与える影響
[SerializeField] float waveDirectionInfluenceByMove = 10f; // 移動が波の向きに与える影響
MeshRenderer meshRenderer;
Material material;
Vector3 position;
Vector3 previousPosition;
void Start()
{
meshRenderer = GetComponent<MeshRenderer>();
material = meshRenderer.material;
}
void Update()
{
previousPosition = position;
position = transform.position;
float dt = Time.deltaTime;
Vector3 diff = position - previousPosition;
// 波の高さの更新
waveSize += waveSizeInfluenceByMove * diff.magnitude / dt;
if (waveSize > maxWaveSize) waveSize = maxWaveSize;
// 波の速度の更新
waveSpeed = -waveSize * k;
waveSize += waveSpeed * dt;
// 波の向きの更新
if (position != previousPosition)
{
diff.y = 0f;
waveDirection = Vector3.Lerp(waveDirection, diff.normalized, waveDirectionInfluenceByMove * Time.deltaTime).normalized;
material.SetVector("_WaveDirection", waveDirection);
}
material.SetFloat("_WaveSize", waveSize);
}
}
ShaderGraph
波の高さの更新の計算が難しい…
頑張って自分の中に落とし込みます…!ありがとうございます!
シェーダーについて追加で質問失礼します。
①オブジェクトのローカル座標と、任意ベクトル(WaveDirection)の内積を取る
②TAUと①を掛ける
③ ②で計算したものをサインに使う(時間を引く)
この一連の計算についてですが、
①で内積のBに入力している部分は Normalize しなくても大丈夫なのでしょうか?
②でTAU を掛ける理由があれば知りたいです。
※今朝まで違う質問を投げていたのですが、解決したため内容を変更させて頂きました。
座標をNormalizeしない理由について
①で内積のBに入力している部分は Normalize しなくても大丈夫なのでしょうか?
まず内積について説明すると、
ローカル座標の点とベクトルWaveDirectionの内積は、点をWaveDirectionへ射影した長さになります。(ベクトルの長さが1の場合)
この長さをSineで利用することで、WaveDirectionの方向へ進むSine波を作ることができます。
関連 : 🍇 内積・外積を使ったグラデーション
Normalizeを入れてしまうと、内積結果xは
数学的な説明
数学的に説明すると、座標
内積は、以下の図の直角三角形の底辺の長さに一致しています。
座標にNormalizeを適用するということは、座標
になってしまいます。(内積結果は、
TAUを乗算する理由
②でTAU を掛ける理由があれば知りたいです。
TAUについて補足すると、TAUは
図付きで大変分かりやすい説明をありがとうございます!
座標の点とベクトルの内積の理解が曖昧でしたが、今回の件でよく分かりました!本書の知識の応用だったんですね。後者についても同様です… 数学的な理解が深まりました!ありがとうございます。
ShadeGraphの本を購入し楽しみながらChapter1から勉強中なのですがChapter28,29で詰まってしまったため何か解決策を知っているのであれば教えてもらいたいです。
サンプルプロジェクトではCanvasの設定をScreenSpace - OverRayにしていても動作しているのですが、自分で新しく作ったプロジェクトではScreenSpace - OverRayだと動作しません。
Unity 2020.2.6f1
URP 10.3.2
ShaderGraph 10.3.2
やったこと:
Unityのバージョン変更
→動作せず
URP,ShaderGraphのバージョンアップ
→動作せず
サンプルプロジェクトから自分のプロジェクトにShaderを移植
→動作せず
よろしくお願いします。
ShaderGraphは機能しているように見えますが、Imageがつぶれているように見えました。
ImageやRawImageのRectTransformを以下のように設定して、実行したときにどうなるかを見てみたいです。
画質は荒いですがこんな感じです。
Materialは本の集中線の自分で作ったものを適用してます。
ちなみにサンプルのConcentrationLine Shaderから作ったMaterialを適用すると以下のエラーが出ます。
ShaderGraphは機能していると思うので、
・ノードのつなぎ方が違う
・ノードのパラメータが違う
などが考えられると思います。
以下のようにノードをつなげば、集中線が出せると思います。
すみませんどうしてもできませんでした...
もしよろしければプロジェクトデータを送るので試してもらうことは可能ですか?
ご迷惑をお掛けしてすみません。
大丈夫です。
Unityプロジェクトのリンクなどを送っていただければ、時間が空いたときに見てみたいと思います。
よろしくお願いします。
修正してみました。
行った作業
-
Vertex Color を マスターノードのBase Color につなぐ (ImageのColorは黒にする)
-
Angle Scale を 1 から 10 に変更する
これ再生したときは問題なく表示されましたか?
自分の方で修正後再生してもやはり表示されなかったのですが...
どうやらCanvasのRender Mode が Screen Space - Overlay だと、
ゲーム再生時に ShaderGraphがついたUIが表示されなくなるみたいですね。
(Unityのバグだと思います)
Canvasを Screen Space - Camera にして、
マテリアルのRender QueueをTransparent(3000)に設定したら
UIが表示されました。
集中線が表示されるようにしたUnityプロジェクトをお渡しします。
本当にありがとうございます。
助かりました。
stepの公式が違う気がします。。。
出力値逆ですよね?
@ 発酵大豆さん
ご報告ありがとうございます。
修正させていただきました。
修正前
修正後
Hey!
In the Chapter 15 "Absolute node" you mention electrical pattern (ノイズから電気パターンを作る). Is it shown anywhere? I can't figure out how to use it this way.
Thanks!
In chapter 27 (🍍 3Dスキャンライン表現) shouldn't we use Position in "Object" mode? Leaving it in "World" will make the scan line move when we move the object (in "Object" the line keeps moving at the same height but in "world" when we move the object UP the line will slide down repeating).
Thank you for the question.
You can use either Object mode or World mode depending on the situation.
When Object mode is selected, the scan lines are affected by the transform (position, scale, rotation) of the Object.
This is good for object effects.
When World mode is selected, the scan lines are not affected by the Object's transform (position, scale, rotation).
This is suitable for world effects.
example : https://styly.cc/ja/tips/unity-shader-worldscanline/
Thanks! I didn't think about that. I now see that "World" space can be also very useful for this effect 🙂
Hey!
In "Chapter 42 🍍 Soap bubbles (Particle System)" you never explain why do we use "Normal Vector" node.
Is it because by multiplying by normal vector we will preserve the circular shape even though we apply distortion to the vertex ?
Sharder Graphで輪郭線が描けるとのことで本を購入、試してみたのですがうまくできずアドバイスいただけませんでしょうか。
chapter 17 dot productの記載そのままのつもりですが、
どうにも輪郭が描けないのです。
(画像が一部ぼやけているので多分あっているという程度です)
Inspectorの設定等はいじっていないので、そこにポイントがあるかもしれません。ご教授いただけませんでしょうか。
なお、Unity 2020.3.0f1にて試行(GitHub配布サンプルと同一バージョン)、
モデルはサンプル内のものを流用にて試しています。
以上、よろしくお願いします。
貼っていただいたシェーダーグラフの画像だと、View Direction と Position の内積をとってしまっていますね。
Position の 代わりに Normal Vector を使ってみてください
Normal Vector ノード
返信ありがとうございます。
本内の絵を拡大してよく見るとNormal Vectorが使われていたのですね。ご指摘いただきありがとうございます。(文書内に赤文字でPositionと書かれていたのでPositionだと思い込んでいました)
Normal Vectorに変え実行したところ、
・DDXYを使用しなければ球(Sphere)はうまく描画できるようでした。球でないモデルでは輪郭線の描画は失敗するようでした。
・DDXYを使用するとどちらもうまく描画できないようでした。
きっとまだ何か間違いがあるとは思うのですが見つけられず…
(DDXY無し…球の表現はうまくいく)
(DDXYあり…黒く表示されるのみになってしまう)
気が向いたらでよいのでもしわかりましたら教えていただけますと幸いです。
返信が遅くなってすみません。
DDXYノードは数値の変化量が大きい部分を抽出するようなノードです。
法線が滑らかに変化する3Dモデルだと輪郭線をうまく抽出できますが、
添付の3Dモデルは、頂点数が少なく、法線の変化が粗いため、DDXYでは輪郭線を抽出できません。
参考 : 例5 : 輪郭線抽出
背面法など、別のアプローチでの輪郭抽出を試してみてはいかがでしょうか。
参考 : https://light11.hatenadiary.com/entry/2018/05/13/183314
かもそば様
アドバイスありがとうございました。他の方法も試してみます!
もっとNode説明を増やしてほしい。
めっちゃわかりやすくてよい。
誤字報告です。
Chapter 01:この本について
「シェーダーを作るのに必要な知識」の最後の行、「ノードを使った表現の実装例をを紹介していきます。」
「を」が重複しています。
よろしくお願いします。
誤字報告ありがとうございます!
修正いたしました。
分かりやすくて重宝させていただいております.
誤植報告です.
Sineの周期は 2π なので、6.218秒に1回 くらいの間隔で明滅します。
2 * 3.14 = 6.28
なので 6.28 秒ではないでしょうか.
よろしくお願いします.
誤字報告ありがとうございます!
修正いたしました。
ありがとうございます!
こんにちは。
重宝させていただいております。
SubstanceDesignerでリニアなテクスチャを書き出したいのですが書き出し時のcolorSpaceの挙動が理解できず、教えていただきたいです。
自環境で検証したところ、
- Linear: ガンマ補正がかかるっているような見た目で出力されている
- sRGB: SDの2Dビュー(sRGBオン)の見た目のまま出力されている
のような結果になりました。
Linearで書き出すと緩急のついたテクスチャが出力され、逆にsRGBで書き出すとリニアなテクスチャが出力されてしまうようです。
本来は
- Linear: SDの2Dビュー(sRGBオフ)の見た目が出力される
- sRGB: SDの2Dビュー(sRGBオン)の見た目が出力される
ではないかと思っています。
かもそばさんの以下の記事でも、Linearで書き出したテクスチャが、元の見た目よりも黒い部分が多く何かしらの補正がかかっているように見えています。
こちら何故かご存知でしょうか?
Color Space を Linear に設定し、テクスチャをエクスポートします。
※sRGBでエクスポートしてしまうと、テクスチャにガンマ補正がかかり、アニメーションにもガンマ補正がかかってしまいます)
https://zenn.dev/r_ngtm/books/shadergraph-cookbook/viewer/tips-substance-texture-linear
はじめまして。
unityのエフェクト周りの情報を集めていて、かもそば様の書籍に行き当たりました。
内容が良さそうだったので、是非社員にも見てもらいたいと思い、できれば社内教育にも活用できたらと思っているのですが、そもそも法人利用は可能でしょうか?
教えてもらえるとありがたいです。
よろしくお願いいたします。