『WING IT!!!』MV解説
『WING IT!!!』MV解説


これは何
- 2025/04/02にTHE LUV BUGSよりリリースされた楽曲『WING IT!!!』のMVを制作した
- この記事では、Renardが担当する部分について解説する (主にUnity部分)
担当
- キャラクターモデリング:O.G.I.
- モデリング、一部映像(遊園地の爆破)、破壊アニメーション:kinankomoti
- Houdini/Blender
それ以外:Renard
- Unity HDRP/After Effects
私とkinankomotiはいろいろ話し合いながら制作した
- キャラクターモデルに関しては、O.G.I.さんが同レーベルの他のMVで使用したモデルを使わせて頂いた
MV全体の構成
- 大きく分けて「遊園地」「宇宙」「コンクリート」の3つのパートで構成されている



- 全体を通して、歌詞は3D空間に出現するようになっている

構想

- 作業は全てfigjam上で行った
- 歌詞を読み合って解釈をし、方向性を統一
- 役割のざっくりとした分担 (というよりは技術スタックによる制限に近いが)
- kinankomoti : Houdini/Blender (モデリング、シミュレーション系)
- Renard : Unity HDRP/After Effects (それ以外全て 基本はUnityでレンダリング)
- リファレンスを集めながら、やってみたい表現を羅列
- 曲を大きな3つのセクションに分け、それぞれに対しシーンを定める
- さらに分割した小セクションで細かい演出を割り当て
モデルを仮置きし、絵コンテ的なものを添える(絵が描けないので)
ある程度固まって取り掛かかった後は、TODOの洗い出し -> TODOの消化のイテレーション
- TODOは依存関係が深いものから優先付け (例えば、文字のモデルが無いと歌詞が配置できないので優先度は高い、など)
Unityのタイムライン構成

- Unity Recorder
- サウンド
- 音
- 歌詞データ制御
- 1拍、1小節のclipを大量に生やしてスナップするやつ
- カメラ制御
- 切り替えはCinemachine、パラーメータをAnimationで制御
- キャラクター制御
- 位置をParentConstraint、表情や動きはAnimation
- ライト制御
- 色やon/off (Activation Track)
- オブジェクト制御
- Animationでメリーゴーランドやゴーカートなどを動かしたり、on/offを切り替えたり
歌詞のシステム

- MusicXMLが貰えたので、C#でパーサーを作り、UnityのTimelineのTrackとして実装した
- 歌詞と時間の情報をjsonで書き出し、kinankomotiはhoudiniを使って文字のsoftbodyシミュレーションをvellumで回し、ペラペラ文字を膨らませる
- fbxで文字を書き出す際に、tangentに膨らんだあとの座標を書き込み、歌詞の出現時の時間をuvに書き込む

- Unity側ではTimelineの時間をシェーダーに渡し、文字の膨らむアニメーションは全てシェーダー
- 一気に膨らんで、空に飛んでいくような動きを実装
- 後は配置だけすれば勝手に歌詞が出現していく仕組み
- 文字の色については、干渉薄膜をベースとしてシェーダーを書いた
- https://github.com/kinakomoti-321/TFI_LUTCreator
カメラ制御
歌詞駆動制御

- 歌詞を映す画角の際は、歌詞の位置に合わせて自動で決まるようにした
- Cinemachine Target Groupをベースに、現在発音中の歌詞と直近の幾つかを自動的にGroupにする(重み付けは時間に対するカーブ)
- Groupにすると、Transformが回転と位置の重心になり、Cinemachine Followで勝手に歌詞を正面に捉えて追従できる
- またCinemachine Group Framingによって、歌詞をどの程度絵に含めるか制御
- 幾つかのフレーズでGroupを区切って、カメラの遷移を自然に (「安直な」「ストーリーで」「横転」みたいな、歌詞の区切りは重みづけを残さず切る的な)
Cinemachineの活用

- 歌詞が無い時はSplineDollyやOrbitalFollow、キャラクターに対してFollow(Lock To Target)など
- パラメータはAnimationで制御
- Dampingや、Recomposer、Camera Offset、Rotation Composerで調整
- Tilt、Pan、Dutch、DollyZoomなどもできる
- 手振れ感(?)はBasic Multi Channel Perlinで実現できる
キャラクターアニメーション
- タイムライン上で、位置、表情、瞬き、リップシンクを制御
- Very Animationでキャラの動きをつける

レンダリング
- RayTracingの設定(Volume)を2つ、レンダリング用のmaxのやつと、editor上で確認する用のraymarchingとか使った安いやつを用意
- Unityには一応PathTracingもあるが、使い物にならなかったので使わなかった
- UnityRecorderはパストレ用のAccumulationの設定があるが、色々うまくいかない
- DOFはCinemachine Auto Focusで、ピントが合う感じができる

- MotionBlur、Tonemapping、Bloomなど軽くポスプロを入れ、あとはAEに任せる
- 録画はUnityRecorderで、ProRes 4444 XQにすると一番画質が良い (より良くする場合、1フレ1フレ撮ってロスレスで書き出し、後で合成するのがよろしいと思う)
グリッチ

- 色々なコーデックでdatabendingを行い、良いやつを組み合わせて合成
- Datamoshはffglitchやそのforkなどで行った
- AEのDatamoshプラグイン(有料)はffglitchのラッパーなので嫌で買わなかったが、後になって思うと、買った方が簡単だよね 嫌なんだけどね
- NTSC風データ損失エフェクトはNTSC-rsを使用

コンポジット(AE)
- コンポジットって何?
- Deep Glow、Magic Bulletとか色々かけた
- 色については何も分かんないので勘で

- このパチンコみたいなロゴはがっつりエフェクトで作った 元のレンダリングはHoudini(kinankomoti)
- Unity Timelineの使い方が悪いのか、カメラ切り替えのタイミングで1フレームおかしくなることがあり(キャラだけ残るとか)、それをごまかすため色々やった
おわりに&感想
SESSIONS2024 WriteUp
これはSESSIONS Advent Calendar 2024の記事です
SESSIONS2024 WriteUp

これは何
2024/11/16~2024/11/17に日本科学未来館で行われたSESSIONSというイベントのWriteUpです
沢山の提出ありがとうございました。 私は作品の上映とか管理とかを主にやっていました
解説1 (Code Graphics Compo)
この、『[SESSIONS2024] 【ゆっくり解説】3分で分かる!「Classic GLSL Graphics」の作り方【SESSIONS】』はCode Graphics Compoで優勝した作品です
詳しく言うと「Code Graphics」という部門のサブカテゴリである「Classic GLSL Graphics」のレギュレーションに則っています
簡単に言うと、外部ライブラリ/リソース無しの生WebGL fragment shaderでお絵描きする部門です(shadertoy的な感じ)

こんな感じで、GLSLが49296文字あるだけです
https://twigl.app/?ol=true&ss=-OBizEQsMADi_j40QI53
ここから動かせますが、20秒くらいコンパイルでブラウザが固まるので気をつけてください
文字の表示について
この作品のおもしろポイントはja/en字幕があるとこくらいなので、それだけ解説します(他はシェーダーお絵描き)
実はコードの前半部分(25000字くらい)はプログラムで自動生成したものなので、見た目より労力はかかってません。 作品全体で2,3日くらいでした

このツールはUnityのエディタ拡張として実装されていて、文章を入れると美咲フォント(8x8のビットマップフォント)に変換してくれます

こんな感じで縦横が区点に対応しており、一枚は全角(JIS X 0208-1990)でもう一枚が半角(JIS X 0201-1976)になっています。
適当なサイトから拾ってきたJIS X to Unicode表を気合いでパースし、文字->Unicode->Texture2Dからサンプル->ビット(uint)という感じで変換してます
美咲フォントは全角8x8、半角4x8(それぞれ横1pxは余白)になっているので、全角はuint(32bit)2個、半角はuint1個でデータを表せます
という事でフォントデータはuintの配列で表し、文章自体は全角半角区別せずにインデックスで管理します(重複した形をまとめるため)
変換結果はこんな感じになります
const int HEXCOUNT=26; const int TEXTCOUNT=2; const int MAXTEXTLEN=17; const uint[] HEX=uint[HEXCOUNT]( 0x00000000u,//Null 0x0E0021E0u,//こ(l) 0x03000070u,//こ(r) 0x884C2210u,//ん(l) 0x00005520u,//ん(r) 0x19119590u,//に(l) 0x4F4A60C0u,//ち(l) 0x07034210u,//ち(r) 0x1D11D3D0u,//は(l) 0x17111350u,//は(r) 0x35535550u,//R 0x00257160u,//e 0x00355550u,//n 0x00346560u,//a 0x00531110u,//r 0x44655560u,//d 0x444C21E0u,//と(l) 0x00300070u,//と(r) 0x8F9F9F80u,//申(l) 0x07474700u,//申(r) 0x222222C0u,//し(l) 0x00004210u,//し(r) 0x8F8FA9E0u,//ま(l) 0x07070160u,//ま(r) 0x0F42C0C0u,//す(l) 0x17111100u//す(r) ); const int[] TEXT0=int[MAXTEXTLEN](1,2,3,4,5,2,6,7,8,9,0,0,0,0,0,0,0); const int[] TEXT1=int[MAXTEXTLEN](10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,0); int[] TEXTLEN = int[TEXTCOUNT](10,17); int[MAXTEXTLEN] getText(int i){int[MAXTEXTLEN] t;if(i==0)t=TEXT0;else if(i==1)t=TEXT1;return t;}
ボトルネックは明らかにgetTextで、これはもうどうしようもなかったです レギュレーションが30secだったので、それに合わせて文章を考えました
レンダリングはこんな感じです
bool inuv(vec2 p) { return all(lessThanEqual(vec2(0),p)) && all(lessThan(p,vec2(1))); } float printHalf(vec2 p,int t) { ivec2 i = ivec2(p * vec2(4,8)); return float(inuv(p) && ((HEX[t] >> (i.x + i.y * 4)) & 1u) == 1u); }
動くコード(Unity拡張+twiglサンプル)はこちらにあるので、試したい方はためしてみてください
おわりに&感想
- なぜUnity拡張なのか : もともと趣味で作ってたプロジェクトがあり、それを流用したから
- Classic GLSL GraphicsのレギュレーションにMRTを追加したのは私です 個人的に2passのリッチなレンダリングなどを期待していましたが、私以外誰も使っていなかったのでちょっと残念でした(自分はlife gameくらいにしか使ってない)
- ShaderJamでComputeShaderを使ってみて、その場で色々な面白さが分かってきたのがとてもShaderという感じで嬉しかった
- 今回のSESSIONSはいろいろなコミュニティに届いていておもしろかったです
VJ ゆるWriteup (VRChat Sequence 16 2023-12-18)
VJ ゆるWriteup (VRChat Sequence 16 2023-12-18)
こちらはジェネ系VJ Advent Calendar 2023の18日目の記事です
要約
- GLSL(Fragment Shader)だけでジェネVJした
はじめに
VRChatのクラブイベント「Sequence」でVJをしました
#SEQ_VRC お疲れさまでした!@loser4dim さんと100%GLSLでVJしました
— Renard_VRC (@Renard_VRC) December 18, 2023
GLSLに愛https://t.co/Xg42rrwZf1 pic.twitter.com/vEfRhWF4nY
使ったもの
- Sh4der Jockey
- Touch Designer
- ComfyUI
構成
全体の構成はこれだけです
TDは動画をNDIで飛ばす装置として使いました

Sh4der Jockey側のパイプラインはこんな感じです
GはIncludeして使いまわすやつで、Fがfragment本体

uvmapがこんな感じだったので、真ん中に出力するの(mainout)と横の二つ(subout)に分けました

なんか
SDXLでフッテージ作る
TDからNDIで送るフッテージはSDXLで作りました
ComfyUIを使いました
こんな感じでノードで使えるので、Automatic1111よりやりやすいです

動画作るのはこれでやりました 他にもいろいろ入れたけど
一つの動画が3.875秒なので、pixelsortで無理やり32個つなげたのを作りました


せっかくなので共有します
1024x1024で長さ2:04です pixelsortのタイミングも同じなので、重ねられます
入力について

Sh4der Jockey側で入力を受けるのですが、MDI以外は受けられないのでゲームパッドを仮想MIDIに変換しました
やり方↓
gamepad to midiできました ありがとうございますhttps://t.co/Px9Hm3qQ4a pic.twitter.com/LhRbF2LA6C
— Renard_VRC (@Renard_VRC) December 12, 2023
触手のイージング
触手の動きはこんな感じです
float tr=1-exp(-time*5); tr+=(.5-.5*cos(TAU*tr))*.5;
初速大きめに動き過ぎて、ちょっと戻る感じ
感想
- 楽しかった
- loserさんのDJについていくのが難しかったので、次はもっとうまくやりたい
- ストロボ最強
VJ ゆるWriteup (VRChat WIREDVEIN 2023-12-01)
VJ ゆるWriteup (VRChat WIREDVEIN 2023-12-01)
こちらはジェネ系VJ Advent Calendar 2023の5日目の記事です
まだ参加者が少ないのでもっと皆さんに書いて欲しい~~
要約
- UnityHDRPでジェネVJやったよ
はじめに
VRChatのクラブイベント「WIREDVEIN」でVJをしました
昨日のWIREDVEINで行ったジェネVJの映像です
— Renard_VRC (@Renard_VRC) December 2, 2023
DJ:@KesiraeVRhttps://t.co/LRkeL8OQLD pic.twitter.com/1lH7Rb86j4
動機
- UnityHDRPのレイマーチングシェーダーを新しいHDRPに対応させたい
イメージ/やりたいこと
レイマーチングでピカピカする
顕微鏡で内臓を見る (見るとこはコントローラーで動かせる)

実装/知見
レイマーチングを新しいHDRPに対応させる
気を付けることとして、HDRP6.9.0を使わないと動きません
HDRP、とくに9.x以前はpreviewになっていてバージョン間の互換性がほぼないので、気をつけポイントです
今回は HDRP14.0.8+Unity2022.3.8f1でやりたいので、それに対応させます
- HDRP6.9.0のLit Shader
- HDRP14.0.8のLit Shader
のDiffを見ながら、書き換えるべき箇所を一つづつ書き換えていきました
- 古い方の"HDRP/Lit":879Line 45997chars 15pass
- 新しい方の"HDRP/Lit":1303Line 69811chars 21pass
という感じで、結構増えています(これは.shaderだけなので、全部展開するともっと増えていると思われます)
ただ、中身を見てみるとそこまで破壊的な変更はなく大きな変更はDXR系のパスくらいなので、レイトレに対応しないのであればやれそうです
結果的に半日かけて書き換え出来ました Shader欲しい方はDMなど下さればあげます
どういう感じで書き換えたかはこちらの殴り書きをご覧ください
RenderingDebuggerが有用でした
Kanetaさんのレイマーチングシェーダーが無ければこれは無理でした ありがとうございます
平面のシェーダーをPBRの力で良く見せる
今回顕微鏡で見る対象はyonatanさんのこれを考えていました
#つぶやきGLSL https://t.co/DJz37Mx6gK
— yonatan (@zozuar) February 2, 2023
vec2 n,q,p=(FC.xy-.5*r)/r.y;
float d=dot(p,p),S=9.,i,a,j;
for(mat2 m=rotate2D(5.);j++<30.;){
p*=m;
n*=m;
q=p*S+t*4.+sin(t*4.-d*6.)*.8+j+n;
a+=dot(cos(q)/S,vec2(.2));
n-=sin(q);
S*=1.2;
}
o+=(a+.2)*vec4(4,2,1,0)+a+a-d; pic.twitter.com/EBVpCJXhMO
これをそのまま出すと内臓のぬるっとした感じが出ないので、PBRの力を借ります
HDRPでShaderをコードで書くのは苦行ですので、ShaderGraphを使います
コードが必要な個所はCustomFunctionNodeを使えばいいので簡単です
今回はyonatanさんのシェーダーをベースに内臓をRenderTextureに書き、ShaderGraph側でHeightToNormal Nodeを使ったり、ClearCoatやDepthOffsetをやるとぬるっとしました
— Renard_VRC (@Renard_VRC) November 24, 2023
これで完成なのですが、謎のエラーが出ました
Shader error in ‘Shader Graphs/ShareNakami_Organ’: Opcode DerivCoarseX not valid in shader model lib_6_3(closesthit). at ShareNakami_Organ(15738) (on d3d11)
これはHDRPでRayTrace OnにしてるとDDX/DDXらへんが使えないので発生します
なんかEditor上だと無視しても普通に見えたのでやったーと思っていたのですが、ビルドできませんでした
(公式の人も無理だと言ってる)
最悪なことにRayTraceをOffにしても何故かエラーが止まず、泣く泣くNormal取るのはあきらめました はあ
有用なライブラリなど
特にMinisとInput Systemの組み合わせはマッピングをすっきり書けてかなり良かったです
今回はコントローラーとMidiを併用したので、そこらへんもいい感じに書けるのが良いでした
マッピング/入力について
コントローラーは当初「顕微鏡動かすならスティックだよな~」程度に考えていたのですが、コントローラーは拍を全部押して取る私のVJスタイル(?)にとても合いました
とても押しやすく疲れにくく、タイミングも合いやすかったです
マッピングはこんな感じでした

コントローラーはこれです なんでもいいので安いやつです
F310ゲームパッド - コンソールスタイル - ロジクールゲーミング
感想
今回やる気が出るまで時間がかかり、前日/当日に8割実装したため、本番直前のビルドで不具合が発生しまくりました(5分前くらいまでビルドしてました)
結局Cookie入れたAreaLightが無いことにされていたのはなぜだったんだ まあできたのでOKです
後AfterParty用に朝日をMidiで操作して昇らせるシーンがあったのですが、AfterPartyが消滅したので深淵に葬られました
VJ ゆるWriteup (VRChat ECHO 2023-10-28)
VJ ゆるWriteup (VRChat ECHO 2023-10-28)
要約
- UnityHDRP+レイマーチングでジェネVJシステムを作ったよ
はじめに
VRChatのクラブイベント「ECHO」でVJをしました
#VRC_ECHO
— Renard_VRC (@Renard_VRC) October 28, 2023
先ほどのECHOで@KesiraeVR さんのVJをさせていただきました!
いつものGLSL100%ではなく、趣向を変えてUnity HDRPを使ってレイマーチングしてみましたhttps://t.co/fnAKOfKZwz pic.twitter.com/f9vyDsqWto
動機
- Sh4derJockey(GLSL)だけでVJするのは楽しいが、ずっとやってると表現が凝り固まってしまう気がしたので
- 楽したい 正規直交基底を書かなくても絵を出したい
- モダンなリアルタイムレンダリングを触ってみたい
コンセプト
アバターと生と死的な感じ
イメージ/やりたいこと
- ré3ちゃんを踊らせたい
- CUEで0b4k3さんが荒ぶるやつ

- 人型モデルが歩く、VJでよく見るやつ

- ré3ちゃんには赤い輪郭線があり、Milk Inside a Bag of Milk Inside a Bag of Milkというゲームを思い出したので、言葉の羅列を画面いっぱいに出したくなった


- 適当なレイマーチングをいれる
いざ実装
HDRPでレイマーチングをやる
Kaneta先生の記事に全部書いてあります
気を付けることとして、HDRP6.9.0を使わないと動きません HDRP、とくに9.x以前はpreviewになっていてバージョン間の互換性がほぼないので、気をつけポイントです 対応するエディタのバージョンもあるので、これを見ます https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@14.0/manual/System-Requirements.html
今回はUnity2019.2.0f1を使います
映像をOBSに送る
https://github.com/keijiro/KlakSpout/tree/v1
v1じゃないと動きません 2019なので
Midi入力を受けとる
https://github.com/keijiro/MidiJack
Minisは動きません 2019なので
文字のシェーダーを書く
"TextMeshPro/Mobile/Distance Field"のシェーダーを改造します
やることは単純で、ノイズでuvを歪めた文字を三回重ねただけです
感想(光)
感想(闇)
Truchet Tilingのやり方
Truchet Tilingのやり方
要約

・↑これ、Truchet Tilingって言うらしい
・セルを構成する辺の中点に固有のハッシュ値を割り当てることで線の接続/切断を表すとうまくいく
・一番下にソースコードも載せておきました
方針
1.uv=fract(n*uv)などでuvをグリッド状にする

2.floor(n*uv)+.5でセルの中央の点を得る

3.中央点から四方向に座標を足して、辺の中点を得る

4.中点の座標をハッシュ関数にかけて、線の接続/切断を決める
(ex:hash12(mid)<.5)
5.1で得たuvと4で得た接続情報を元にセルの中身を描画する
実装
1~3は割愛します
4
vec2 tci(vec2 uv) { return round(uv*2.)*.5; }
const vec2[4] dir = vec2[4](vec2(1,0),vec2(0,1),vec2(-1,0),vec2(0,-1)); vec2[4] quv; int co=0; float th=mix(.2,.8,sin(time)*.5+.5); for(int i=0;i<4;i++) { vec2 id=tci(cen+dir[i]*.5); if(hash12(id)<th)quv[co++]=dir[i]; }
辺の中点idを得る際、隣のセルとハッシュ値を一致させるため、計算誤差が怖いのでtciという関数を作って丸め込んでいます。
また後に使うため、接続すると決めた点を配列quvに入れています。
5
// qn:接続点がn個のセルの描画をする float q0(vec2 uv) float q1(vec2 uv,vec2 p0) float q2(vec2 uv,vec2 p0,vec2 p1)
vec2 p=uvf*2.-1.; if(co==0)c+=q0(p); if(co==1)c+=q1(p,quv[0]); if(co==2)c+=q2(p,quv[0],quv[1]); if(co==3) { if(hash12(cen+.42)<.5) c+=q1(p,quv[0]),c+=q2(p,quv[1],quv[2]); else c+=q1(p,quv[1]),c+=q2(p,quv[0],quv[2]); } if(co==4) { if(hash12(cen)<.5) c+=q2(p,quv[0],quv[1]),c+=q2(p,quv[2],quv[3]); else c+=q2(p,quv[0],quv[2]),c+=q2(p,quv[1],quv[3]); }
接続する点の数coで描画の場合分けをします。
また、セルのuvであるuvfを扱いやすい形に変えます(uv*2.-1.)
q0,q1,q2という関数を定義します。これは接続点がn個のセルの描画をする関数です。
今回の場合、接続点3,4つの描画は(q1+q2)と(q2,q2)で代用しました。ここら辺はいい感じの関数を作るといいと思います
気を付けるのはq2以上で、接続点の並びによって曲線/直線で描き分けるなど、描画を変えるといいと思います

結果
#GLSL
— Renard_VRC (@Renard_VRC) August 11, 2023
Truchet Tiling pic.twitter.com/Zb87vQbq0Y
ソースコード
https://gist.github.com/Forenard/eb96f682c46aeb3b10cacd6812f29ba0
GLSLでノイズの等高線をきれいに描く
GLSLでノイズの等高線をきれいに描く
要約
- 普通にやると線が等幅にならない
- 勾配を取って、その方向の直線上で評価するときれいな等高線が得られる
このような等高線が得られます
愚直にやった場合
まず考えつくのはfract(noise(uv)*5.0)<0.2のような実装ですが、これでは等高線が等幅になりません
実際にやってみると
vec2 p=FC.xy/r; float l=.2,f=5.; float n=snoise2D(p*5.)*.5+.5; float c=float(fract(n*f)<l); o+=c;

確かに等幅にならないことが確認できます
これは、ノイズの変化量が一定でないため起こります
改善案
ノイズに対する勾配を取ることを考えます
手順は以下のようにします
- uvをx,yそれぞれの方向に少しだけずらしてノイズを取り、勾配を計算する
floor(noise(uv)*5.0)とfloor(noise(uv+dir*w)*5.0)を比べて、領域が違う場合線を引く (dir:勾配の方向、w:線の太さ)
こんなイメージです
vec2 uv=FC.xy/r; float w=.005,f=5.; #define noise(p) snoise2D((p)*5.) const vec2 e=vec2(1e-4,0); float n0=noise(uv+e.xy); float n1=noise(uv-e.xy); float n2=noise(uv+e.yx); float n3=noise(uv-e.yx); vec2 dir=normalize(vec2(n0-n1,n2-n3)); float i0=floor((noise(uv)*.5+.5)*f); float i1=floor((noise(uv+dir*w)*.5+.5)*f); float c=float(abs(i0-i1)>.5); o+=c;

追記
@phi16さんより https://iquilezles.org/articles/distance/ を使ってはどうかと教えて頂いたのでそちらでも実装してみます
vec2 uv=FC.xy/r; float w=.01,f=5.; #define noise(p) snoise2D((p)*5.) const vec2 e=vec2(1e-4,0); float n0=noise(uv+e.xy); float n1=noise(uv-e.xy); float n2=noise(uv+e.yx); float n3=noise(uv-e.yx); vec2 g=vec2(n0-n1,n2-n3)/(2.*e.x); float i0=fract((noise(uv)*.5+.5)*f); float c=float(i0/length(g)<w); o+=c;

あまり見た目が変わらず、こちらの方が軽いのでこっちでいい気がします ただ6回やってるので場合によっては私の実装の方が綺麗に出るかもしれません(分からず)
また、今回は実装していませんがsmoothstepを使うことでジャギが軽減されます
まとめ
ノイズを6回(iq先生の方法だと5回)評価するので若干重いですが、その分きれいな等高線が得られます
また、副次的に勾配が取れるのでこのような表現も簡単にできます
#GLSL
— Renard_VRC (@Renard_VRC) July 5, 2023
等高線ゴねぇ pic.twitter.com/4ejcV1zPqG

