このサイトではJavaScriptについては教えてないと同様にGLSLについても教えていません。 それは本当に大きなトピックです。GLSLを学びたいのであればこれらの記事から始めてみて下さい。
すでにGLSLを知っている場合はデバッグのヒントをいくつか紹介します。
新しくGLSLシェーダーを作成し何も表示されない場合、一般的に最初にするのはフラグメントシェーダーでソリッドカラーに変更する事です。例えばシェーダーの一番下を以下のようにします。
void main() { ... gl_FragColor = vec4(1, 0, 0, 1); // red }
描画しようとしたオブジェクトが表示されれば、その問題がフラグメントシェーダーに関係している事がわかります。良くないテクスチャ、初期化がないuniform変数、間違った値を持つuniform変数の可能性がありますが、私には見るべきポイントがあります。
いくつかをテストするために入力値を描画してみようと思います。 例えばフラグメントシェーダーで法線を使用している場合は次のように追加します。
gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1);
法線は-1から+1までなので、0.5を掛けて0.5を足すと0.0から1.0までの値が得られて色で判別できて便利です。
動作すると知ってるコード変更をいくつか試してみて下さい。正常な通常の描画がどのように見えるか目に見えてわかるようになります。 通常に見えない箇所があれば、どこを見て直せば良いかのヒントがあります。 フラグメントシェーダーで法線を操作している場合、その操作の結果を描画するために同じテクニックが使えます。
テクスチャを使用している場合も同様に、テクスチャ座標で以下のように描画できます。
gl_FragColor = vec4(fract(vUv), 0, 1);
fract
は0から1の範囲外のテクスチャ座標を使用している場合に使用します。
これは texture.repeat
が1よりも大きい値に設定されている場合によく見られます。
フラグメントシェーダーの全ての値に対して同様の事ができます。
その範囲を把握し、0.0から1.0にスケーリングし gl_FragColor
に設定するコードを追加します。
テクスチャを確認するには CanvasTexture
や DataTexture
が動作するもので試してみて下さい。
逆に言えば gl_FragColor
を赤に設定しても何も表示されない場合、問題は頂点シェーダーに関連したものにあるかもしれません。
一部の行列が間違っていたり、attributesが間違ったデータを持っていたり、設定が間違っていたりする事があります。
私ならまず行列を見ます。renderer.renderer.render(scene, camera)
の呼出直後にブレークポイントを設定し、インスペクタで展開を始めるかもしれません。
カメラのワールド座標とプロジェクション座標は NaN
でいっぱいではないのか?
シーンを展開し children
を見てみるとワールド座標が妥当に見えるか( NaN
がない)、各行列の最後の4つの値がシーンにとって妥当に見えるかを確認します。
シーンが50 x 50 x 50 x 50の単位であるはずが、いくつかの行列が552352623.123の場合は明らかに何かが間違っている事がわかります。
フラグメントシェーダーの時と同様に、頂点シェーダーの値をフラグメントシェーダーに渡すと頂点シェーダーから値を描画する事もできます。
両方のシェーダーでvaryingを宣言し、正しい値なのかわからない値を渡します。
実際にシェーダーが法線を使っている場合、値が0.0から1.0になるように vNormal
を値に設定し法線を表示するようにします。
描画結果を見て予想通りか確認します。
もう一つの良い点はよりシンプルなシェーダーを使う事です。
MeshBasicMaterial
でデータを描画できますか?
可能であれば試してみて期待通りに表示される事を確認して下さい。
期待通りでない場合、ジオメトリをビジュアライズできる最もシンプルな頂点シェーダーは何でしょうか? 通常は次のようなシンプルなものです。
gl_Position = projection * modelView * vec4(position.xyz, 1);
それが動作する場合は一度に少しずつ変更を追加していきます。
もう一つの方法はShader Editor extension for Chromeを使うか、他のブラウザでは同様なものを使う事です。 他のシェーダーがどのように動作してるか見る良い方法です。また、上記で記載してきたフラグメントシェーダーの変更を行うとライブで結果確認できるので良いです。