回答:
いいえ。シェーダーに明示的なワールドマトリックスがあることはありません。
理由の詳細な説明はここにありますが、短いバージョンは非常にシンプルです。これが必要になることはなく、浮動小数点の精度が失われる可能性があります。
ワールドスペースが大きすぎる場合は、原点から遠いカメラが浮動小数点の精度の問題を引き起こす可能性があります。
すべてのワールド空間は、モデル空間とカメラ空間の仲介にすぎません。カメラと他のすべてのオブジェクトを同じ空間で表現できる場所です。しかし、それを使用するのは、ワールドからカメラへの行列を生成することだけです。それをモデルからワールドへの行列すべてに適用して、モデルからカメラへの行列を作成します。
行列計算に浮動小数点数の代わりにdoubleを使用することにより、C ++での精度の問題に対処できます。これらをシェーダーにアップロードする前に、これらをフロートに戻すことができます。
では、なぜシェーダーで明示的なワールドスペーストランスフォームが必要になるのでしょうか。あなたのソースコードでは、はい。しかし、シェーダーでは?カメラスペースではできないことをどうすればよいでしょうか。
照明は、ワールドスペースと同じくらい簡単にカメラスペースで行うことができます。あなたがしなければならないすべてはあなたのライトの位置/方向をカメラ空間に変換することです。結局のところ、カメラ空間はワールド空間と同じスケールです。この変換は、フレームごと、ライトごとに1回行います。CPUでもパフォーマンスの負荷はほとんどありません。
したがって、シェーダーを明示的なワールドスペーストランスフォームに公開しても意味がありません。これは、マトリックスに折りたたむ中間ステップにすぎません。
シェーダーで追加の行列乗算を行うことはありません。トリックは、CPUでフレームごとに1回行列の乗算を行い、最終結果を頂点シェーダーにアップロードすることです。これにより、ワールドとビューが別々に表示されているか連結されているかに関係なく、頂点ごとの行列乗算によって1つの位置が得られます。
多くの場合、とにかく、他の目的のために、頂点シェーダーでワールド位置を設定する必要があります。たとえば、鏡面反射光を評価するためにピクセルシェーダーに渡すには、ビューベクトルを計算する必要があります。
local-to-worldマトリックスは、タンジェントベクトルと法線ベクトル[1]をワールドスペースにシェーディングするために変換するためにも必要です。別の行列のセット)。
したがって、IMOには、ローカルから世界へ、およびワールドからクリップへの2つのマトリックスがあることは理にかなっています。後者は、ビューマトリックスと投影マトリックスの積です。両方を頂点シェーダーに渡し、次のような乗算を行います。
posWorld = mul(posLocal, matLocalToWorld)
posClip = mul(posWorld, matWorldToClip)
[1](不均一なスケーリングがない限り。その場合、法線はローカルからワールドへの行列の逆転置によって変換する必要があります。)