私のようなどのように材料系のまわりで私の頭をラップしようとしているこの、これは実装されています。これらの強力でユーザーフレンドリーなグラフのようなシステムは、プログラマーと非プログラマーの両方がシェーダーをすばやく作成できるようにする方法として比較的一般的であるようです。ただし、グラフィックスプログラミングの私の比較的限られた経験から、私はそれらがどのように機能するか完全にはわかりません。
バックグラウンド:
そのため、以前に単純な OpenGLレンダリングシステムをプログラミングしたことがある場合は、通常、手動で作成した静的GLSLファイルからシェーダーを読み込み、コンパイル、リンクするMaterialクラスを作成します。また、通常、このクラスを、GLSLの統一変数にアクセスするための単純なラッパーとして作成します。簡単な例として、基本的な頂点シェーダーとフラグメントシェーダーがあり、テクスチャを渡すための追加の均一なTexture2Dがあるとします。私のMaterialクラスは、これら2つのシェーダーをマテリアルに読み込んでコンパイルし、その時点から、そのシェーダーのTexture2Dユニフォームを読み書きするための単純なインターフェイスを公開します。
このシステムをもう少し柔軟にするために、私は通常、任意の名前/タイプのユニフォームを渡すことができるようにシステムを記述します[ie:SetUniform_Vec4( "AmbientColor"、colorVec4);]。これは均一な材料中に存在する場合、「colorVec4」と呼ばれる特定の4DベクトルにAmbientColorを均一に設定します。]。
class Material
{
private:
int shaderID;
string vertShaderPath;
string fragSahderPath;
void loadShaderFiles(); //load shaders from files at internal paths.
void buildMaterial(); //link, compile, buffer with OpenGL, etc.
public:
void SetGenericUniform( string uniformName, int param );
void SetGenericUniform( string uniformName, float param );
void SetGenericUniform( string uniformName, vec4 param );
//overrides for various types, etc...
int GetUniform( string uniformName );
float GetUniform( string uniformName );
vec4 GetUniform( string uniformName );
//etc...
//ctor, dtor, etc., omitted for clarity..
}
これは機能しますが、Materialクラスのクライアントは信仰だけでユニフォームにアクセスする必要があるため、悪いシステムのように感じられます。ユーザーは、強制されるため、各マテリアルオブジェクトにあるユニフォームに多少注意する必要があります。それらをGLSL名で渡します。1〜2人でシステムを操作する場合は、それほど大きな問題ではありませんが、このシステムが非常に適切に拡張できるとは思えません。OpenGLレンダリングシステムをプログラミングする次の試みを行う前に、平準化したいと思います。少しアップ。
質問:
私は今のところそこにいるので、私は他のレンダリングエンジンがどのようにマテリアルシステムを処理するかを研究しようと努めてきました。
このノードベースのアプローチは優れており、最新のエンジンとツールでユーザーフレンドリーなマテリアルシステムを作成するための非常に一般的なシステムのようです。私が言うことができることから、それらはグラフデータ構造に基づいており、各ノードはマテリアルのシェーダーの側面を表し、各パスはそれらの間のある種の関係を表します。
私が言うことができることから、そのようなシステムの実装は、さまざまなサブクラス(TextureNode、FloatNode、LerpNodeなど)を持つMaterialNodeクラスのように単純です。各MaterialNodeサブクラスにはMaterialConnectionsがあります。
class MaterialConnection
{
MatNode_Out * fromNode;
MatNode_In * toNode;
}
class LerpNode : MaterialNode
{
MatNode_In x;
MatNode_In y;
MatNode_In alpha;
MatNode_Out result;
}
これは非常に基本的な考え方ですが、このシステムのいくつかの側面がどのように機能するかについては、少し不確かです。
1.)Unreal Engine 4が使用するさまざまな「マテリアル式」(ノード)を見ると、それぞれにさまざまなタイプの入力および出力接続があることがわかります。一部のノードはフロートを出力し、一部の出力ベクター2、一部の出力ベクター4などを出力します。さまざまな入力および出力タイプをサポートできるように、上記のノードと接続を改善するにはどうすればよいですか?MatNode_OutをMatNode_Out_FloatおよびMatNode_Out_Vec4(など)でサブクラス化することは賢明な選択でしょうか?
2.)最後に、この種のシステムはGLSLシェーダーとどのように関係していますか?UE4をもう一度見ると(上でリンクされている他のシステムについても同様)、ユーザーは最終的に、いくつかのマテリアルノードを、シェーダーパラメーター(基本色、金属、光沢、放射率など)を表すさまざまなパラメーターを持つ大きなノードに接続する必要があります。 。私の当初の想定では、UE4にはさまざまなユニフォームを備えたハードコーディングされたある種の「マスターシェーダー」があり、ユーザーが「マテリアル」で行うすべてのことは、ノードを「マスターノード」。
ただし、UE4のドキュメントには次のように記載されています。
「各ノードには、特定のタスクを実行するように指定されたHLSLコードのスニペットが含まれています。これは、マテリアルを構築するときに、ビジュアルスクリプトを使用してHLSLコードを作成することを意味します。」
それが本当なら、このシステムは実際のシェーダースクリプトを生成しますか?これはどのように機能しますか?