Saya mencoba membungkus kepala saya di sekitar bagaimana sistem material seperti ini , ini diimplementasikan. Sistem seperti grafik yang kuat dan ramah pengguna ini nampaknya relatif umum sebagai metode yang memungkinkan programmer dan non-programmer untuk dengan cepat membuat shader. Namun, dari pengalaman saya yang relatif terbatas dengan pemrograman grafis, saya tidak sepenuhnya yakin bagaimana cara kerjanya.
Latar Belakang:
Jadi, ketika saya telah memprogram sistem rendering OpenGL sederhana sebelumnya, saya biasanya membuat kelas Material yang memuat, mengkompilasi, dan menghubungkan shader dari file GLSL statis yang saya buat secara manual. Saya juga biasanya membuat kelas ini sebagai pembungkus sederhana untuk mengakses variabel seragam GLSL. Sebagai contoh sederhana, bayangkan saya memiliki vertex shader dasar dan fragmen shader, dengan Texture2D ekstra seragam untuk melewatkan tekstur. Kelas Material saya hanya akan memuat dan mengkompilasi dua shader menjadi sebuah materi, dan sejak saat itu akan mengekspos antarmuka sederhana untuk membaca / menulis seragam Texture2D dari shader itu.
Untuk membuat sistem ini sedikit lebih fleksibel, saya biasanya menulisnya dengan cara yang memungkinkan saya mencoba untuk lulus seragam dari semua nama / tipe [yaitu: SetUniform_Vec4 ("AmbientColor", colorVec4); yang akan mengatur seragam AmbientColor ke vektor 4d tertentu yang disebut "colorVec4" jika seragam itu ada di material.] .
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..
}
Ini berfungsi tetapi rasanya seperti sistem yang buruk karena fakta bahwa klien dari kelas Material harus mengakses seragam hanya berdasarkan keyakinan - pengguna harus agak menyadari seragam yang ada di setiap objek material karena mereka dipaksa untuk berikan nama GLSL mereka. Ini bukan masalah besar ketika hanya 1-2 orang yang bekerja dengan sistem, tapi saya tidak bisa membayangkan sistem ini akan berskala sangat baik sekali, dan sebelum saya melakukan upaya berikutnya dalam pemrograman sistem rendering OpenGL, saya ingin naik level sedikit.
Pertanyaan:
Di situlah saya sejauh ini, jadi saya telah mencoba mempelajari bagaimana mesin rendering lain menangani sistem material mereka.
Pendekatan berbasis simpul ini sangat bagus dan tampaknya menjadi sistem yang sangat umum untuk menciptakan sistem material yang ramah pengguna dalam mesin dan peralatan modern. Dari apa yang saya tahu mereka didasarkan pada struktur data grafik di mana setiap node mewakili beberapa aspek shader dari materi Anda dan setiap jalur mewakili beberapa jenis hubungan di antara mereka.
Dari apa yang dapat saya katakan, menerapkan sistem semacam itu akan sesederhana kelas MaterialNode dengan berbagai subclass (TextureNode, FloatNode, LerpNode, dll.). Di mana setiap subclass MaterialNode akan memiliki MaterialConnections.
class MaterialConnection
{
MatNode_Out * fromNode;
MatNode_In * toNode;
}
class LerpNode : MaterialNode
{
MatNode_In x;
MatNode_In y;
MatNode_In alpha;
MatNode_Out result;
}
Itu ide yang sangat mendasar , tetapi saya sedikit tidak yakin tentang bagaimana beberapa aspek dari sistem ini akan bekerja:
1.) Jika Anda melihat berbagai 'Ekspresi Material' (node) yang digunakan Unreal Engine 4 , Anda akan melihat bahwa mereka masing-masing memiliki koneksi input dan output dari berbagai jenis. Beberapa node keluaran mengapung, beberapa vektor output2, beberapa vektor output4, dll. Bagaimana saya dapat meningkatkan node dan koneksi di atas sehingga mereka dapat mendukung berbagai jenis input dan output? Apakah subkelas MatNode_Out dengan MatNode_Out_Float dan MatNode_Out_Vec4 (dan seterusnya) menjadi pilihan yang bijak?
2.) Akhirnya, bagaimana sistem semacam ini berhubungan dengan shader GLSL? Melihat lagi UE4 (dan juga untuk sistem lain yang terhubung di atas), pengguna diharuskan untuk akhirnya menyambungkan beberapa node material ke node besar dengan berbagai parameter yang mewakili parameter shader (warna dasar, metalness, gloss, emissiveness, dll.) . Asumsi awal saya adalah bahwa UE4 memiliki semacam 'master shader' dengan kode yang seragam dengan berbagai seragam, dan segala sesuatu yang dilakukan pengguna dalam 'materi' mereka hanya diteruskan ke 'master shader' ketika mereka memasukkan node mereka ke dalam ' master node '.
Namun, dokumentasi UE4 menyatakan:
"Setiap node berisi potongan kode HLSL, yang ditunjuk untuk melakukan tugas tertentu. Ini berarti bahwa ketika Anda membangun sebuah Bahan, Anda membuat kode HLSL melalui skrip visual."
Jika itu benar, apakah sistem ini menghasilkan skrip shader nyata? Bagaimana tepatnya cara kerjanya?