見出し画像

【VRChat】プログラマが最速でシェーダーを書くための学習ガイド

概要

この記事は、プログラム(特にC系)を書いたことのある人向けに、Unityでシェーダーを書くために必要な学習ルートを示したものです。
VRchat(BuiltinRP)での使用を想定しているため、ShaderGraphについてはあまり言及しません。
※作者自身も学習しながら、この記事を更新します。細かい誤りがあるかもしれませんがご容赦ください。

はじめに

私は、CとC#を少し書いた経験があり、ここ半年くらいは、VRChatのUDON#を触ったりしていました。そして、VRC内のシェーダー技術を見るうちに、自分も書いてみたくなったわけです。でも、シェーダーの学習は、プログラムほど流れがはっきり分からず、参考文献も散らばっていて分かりにくい印象を受けました。
そこで、私がどのような順番で、どのようなサイトを参考に学習したのかを示そうと思います。
あくまで、UnityでのC#経験があった私にとって理解しやすい学習経路ですが、誰かの参考になれば幸いです。

ステップ0 シェーダーが何かを理解する

まずは今から学習しようというシェーダーが何であるかを理解しなければ始まりません。そのために、一般的なシェーダーの考え方と、Unityでのシェーダーの考え方に分けて見ていきます。

ステップ0-1 一般的なシェーダーを知る

シェーダーは、3Dオブジェクトの描画に関わるプログラムです。シェーダーは、一般的には、頂点シェーダーとフラグメントシェーダーに分かれます。まずはこの2つのシェーダーの役割を理解しましょう。
動画ですが、以下のUnity公式の動画が非常に分かりやすいです。

ステップ0-2 Unityでのシェーダーを知る

ステップ0-1で、頂点シェーダーとフラグメントシェーダーを学習しました。しかし、Unityでは、Surfaceシェーダーというものが用意されています。
一般的には、頂点シェーダーで描画位置を決め、フラグメントシェーダーで、マテリアルの色や材質、ライトの計算をします。しかし、高度なシェーダーを書かないなら、頂点の位置を歪ませたり、ライトの反射そのものを変化させたりすることはないでしょう。そこで、UnityのSurfaceシェーダーでは、「色、透明度、金属感、滑らかさ」といった、ごく基本的なパラメータのみを操作できるようになっています。できることは少し狭くなりますが、文法が易しいので、後のステップ1でも、surfaceシェーダーの学習から始めます。

ステップ0-3 シェーダー言語を知る

シェーダーを書く時に使う言語にはいくつか種類があります。私が学習する中で知ったものとして、
・GLSL
・HLSL
・ShaderLab
があります。しかし、以下で紹介するのは、ShaderLabのみです。GLSLやHLSLは、Unityよりもさらに低レベルな部分(DirectXなど)で使われている印象を受けました。Unityでは、基本的にShaderLabという言語でシェーダーを記述します。
自分でシェーダーについて調べる時は、これらのうちのどの言語について書かれているのかを気にすると良いでしょう。

ステップ1 とりあえず書いてみる

ステップ1-0 環境構築

環境構築なんてのは大げさで、シェーダーの文法を補完してくれる、VisualStudioの拡張機能を導入します。VSは、デフォルトでは、ShaderLabのコーディングを一切補完してくれません。以下のマーケットプレイスからダウンロードして実行し、インストールしましょう。C#などの補完に比べると、かなり弱いですが、ないよりはマシです。

ステップ1-1 とりあえず真似をする

プログラムを書いたことがある人は特にですが、まずは真似をして書いてみましょう。シェーダーは、C言語でいうincludeや、main関数がエントリポイントになっていることのような、いわゆる"お約束"の文法が多いです。何種類かのsurfaceシェーダーを書いてみて、書き換える必要がある場所とない場所を切り分けていきましょう。
真似をして書くには、以下の、ちくわさんの記事が圧倒的におススメです。

具体例が30近くあるのと、何より、最小要件のシェーダーから書き始めるので、コードに必須な部分と不要な部分が分かりやすく学習できます。
ひとまず、上から5~10個くらい書いてみて、書き方が理解できて来たら、同記事内の気になるシェーダーを書いてみたり、他記事のシェーダーを調べると良いと思います。
この記事は、この後の説明でも何度も引用させていただきます。

ステップ1-2 自分でsurfaceシェーダーを書いてみる

ステップ1-1で、ひとまずsurfaceシェーダーの書き方に慣れたと思います。Input構造体に、処理で使いたい変数を入れておき、surf関数で処理を行うというのは分かりました。ですが、自分で書くとなると、Inputで何の情報が使
えるのか。組み込み関数には何があるのか。などが気になるところです。

以下のサイトなどは、情報がスッキリまとまっていました。チートシートとして便利です。

とはいえ、この辺の情報は、公式ドキュメントを見れば全て書いています。
以下に、Unity公式の、surfaceシェーダーの記述、組み込み変数、シェーダーで使えるincludeファイル、組み込み関数のドキュメントを示します。
できることとできないことの境界が見えてくるので、ぜひ軽く目を通してみてください。

ステップ1-3 頂点・フラグメントシェーダーを書いてみる

筆者も現在学習中です…
ひとまず、ステップ1-1で示したサイトの中で、参考になったものを示しておきます。

このなびかせるシェーダーは、頂点シェーダー+surfaceシェーダーで書かれています。文法的にはsurfaceシェーダーの記述と大差ない形で、頂点シェーダーの動きを実感できるので、おすすめです。

以下も同サイトのものです。こちらはsurfaceシェーダーを使わず、頂点シェーダーとフラグメントシェーダーを使用しています。surfaceシェーダーに比べ、入出力の構造体の定義がやや複雑になりますが、surfaceシェーダーではできない表現の理解に役立つと思います。

ステップ2 シェーダーに使える素材を知る

ステップ1では、丁寧に学習した方なら、シェーダーを結構な数書いたかと思います。しかし、シェーダーの処理に利用したデータは、座標、テクスチャ、視線方向などの情報が主だと思います。このステップ2では、シェーダーでよく使われる手法や、便利なノイズテクスチャを紹介します。

ステップ2-1 ディスタンスフィールド

またしてもこちらの記事をお借りしますが、まずはこのシェーダーを見てみてください。

原点からの水平方向の距離を利用して、円を書いています。このように、座標間の距離を利用して描画する考え方には、ディスタンスフィールドという名前があるようです。覚える必要はないと思いますが、表現の幅を増やすためには知っておくのがよいと思ったので、紹介します。以下の記事が大変参考になりました。
※GLSLベースの記事なので、そのままは利用できません。

ステップ2-2 ノイズテクスチャ

星空がきらめいたり、オーロラが揺れる空、そんなものを描画しようと思うと、綺麗なテクスチャを書かないといけないですよね…
と、思いつめる必要はありません!幾何学的なパターンには、ステップ2-1のディスタンスフィールドが便利でしたが、オーロラのような柔らかい不規則な模様を描くには、ノイズテクスチャが便利です!
ノイズには様々なものがあり、種類を知れば、現実世界の不規則な模様などの再現に役立ちます。

代表的なノイズ:引用元(https://nn-hokuson.hatenablog.com/entry/2017/01/27/195659)

参考記事選定中…

ステップ2-3 ShaderGraphチュートリアル

Unityには、ShaderGraphという、視覚的に、途中経過を見ながらシェーダーを生成できる、ノードベースのエディタがあります。これは非常に優秀なのですが、URPやHDRPでしか使えないようで、VRChatにそのまま持ち込むことができません…

ShaderGraphのノード:引用元(https://unity.com/ja/features/shader-graph)

しかし!ShaderGraphの記事や動画を参考にすることは可能です!
YouTubeでシェーダーのチュートリアルを検索すると、ShaderGraphの動画がメインにヒットします。これをそのまま使うことはできませんが、真似しながらコードで打ち直すことで、大変良い学びになります。

ShaderGraphを真似してコードで打つには、1つ障害があります。それは、ShaderGraphに内蔵されているノード(関数)が、コーディングでは使えないという点です。しかし、Unity公式が、ShaderGraphのノードが内部でどのようなコードで実現されているかを公開してくれています!神!
例えば、以下の図に示しているのは、Gradient Noiseを生成するノードです。公式ドキュメントでこのノードのページを見てみると、コードでの書き方が示されています!
(ちなみに、ユーザー定義関数はCと同じ文法で使えます。)

GradientNoiseノード
公式ドキュメントに示されたコード

このように、ShaderGraphからコーディングを学ぶのは、意外とコストが低いです。参考にしたいシェーダーの記事/動画がShaderGraph製であっても、ぜひ参考にしてみましょう。

ステップ3 その他のシェーダーを知る

筆者も学習中
主にジオメトリシェーダーについて書きたいと考えています。

その他参考になったサイトリンク集

この記事と趣旨が似ています。シェーダー学習の概要や、どんな"先"があるのかを知るのに良いと思います。

ShaderLabではなくGLSLでの解説で、直接参考にはしにくいですが、フラグメントシェーダーについて深く説明されています。本気でシェーダーの理論を勉強したい人はぜひ。

ステップ2-3でも書きましたが、UnityのShaderGraph公式ドキュメントは参考になることが多いです。

ShaderLabを書く上では全然使いませんが、GLSLやHLSLの記事を参照するときに、ちょっと便利かと思って載せています。

書籍です。ShaderLabではなくHLSLなので、直接参考にはしにくいです。また、584ページあって読むのが大変です。しかし、物体の光の反射をはじめとする、3Dグラフィックの基礎から、シェーダーの理論を解説した教科書に当たります。Unityでのシェーダーを学んで、本気で3Dグラフィックを学習したいとなった方は読んでみてもよいのでは?
(筆者もチビチビ読んでます。道のりは長い…)

この記事が気に入ったらサポートをしてみませんか?