Tôi đang cố gắng che giấu cách các hệ thống vật chất như thế này , điều này được thực hiện. Các hệ thống giống như đồ thị mạnh mẽ và thân thiện với người dùng này dường như tương đối phổ biến như một phương pháp cho phép các lập trình viên và những người không phải lập trình viên nhanh chóng tạo ra các shader. Tuy nhiên, từ kinh nghiệm tương đối hạn chế của tôi với lập trình đồ họa, tôi không hoàn toàn chắc chắn về cách chúng hoạt động.
Lý lịch:
Vì vậy, khi tôi đã lập trình các hệ thống kết xuất OpenGL đơn giản trước đây, tôi thường tạo một lớp Vật liệu tải, biên dịch và liên kết các shader từ các tệp GLSL tĩnh mà tôi đã tạo thủ công. Tôi cũng thường tạo lớp này như một trình bao bọc đơn giản để truy cập các biến thống nhất GLSL. Một ví dụ đơn giản, hãy tưởng tượng rằng tôi có một shader đỉnh cơ bản và shader mảnh, với một Texture2D đồng nhất thêm để truyền một kết cấu. Lớp Vật liệu của tôi chỉ đơn giản là tải và biên dịch hai shader đó thành một vật liệu, và từ đó, nó sẽ hiển thị một giao diện đơn giản để đọc / ghi đồng phục Texture2D của shader đó.
Để làm cho hệ thống này linh hoạt hơn một chút, tôi thường viết nó theo cách cho phép tôi cố gắng vượt qua đồng phục của bất kỳ tên / loại nào [ví dụ: SetUniform_Vec4 ("AmbientColor", colorVec4); sẽ đặt đồng phục AmbientColor thành một vectơ 4d cụ thể gọi là "colorVec4" nếu đồng phục đó tồn tại trong vật liệu.] .
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..
}
Điều này hoạt động nhưng cảm giác như một hệ thống tồi tệ do thực tế là khách hàng của lớp Vật liệu phải truy cập đồng phục một mình - người dùng phải nhận thức được phần nào về đồng phục trong mỗi đối tượng vật chất vì họ bị buộc phải vượt qua họ bằng tên GLSL của họ. Đó không phải là vấn đề lớn khi chỉ có 1-2 người làm việc với hệ thống, nhưng tôi không thể tưởng tượng hệ thống này sẽ mở rộng rất tốt, và trước khi tôi thực hiện nỗ lực tiếp theo trong việc lập trình hệ thống kết xuất OpenGL, tôi muốn lên cấp lên một chút.
Câu hỏi:
Đó là nơi tôi ở cho đến nay, vì vậy tôi đã cố gắng nghiên cứu cách các công cụ kết xuất khác xử lý các hệ thống vật liệu của họ.
Cách tiếp cận dựa trên nút này là tuyệt vời và nó dường như là một hệ thống cực kỳ phổ biến để tạo ra các hệ thống vật liệu thân thiện với người dùng trong các công cụ và công cụ hiện đại. Từ những gì tôi có thể nói họ dựa trên cấu trúc dữ liệu đồ thị trong đó mỗi nút đại diện cho một số khía cạnh đổ bóng của tài liệu của bạn và mỗi đường dẫn đại diện cho một loại mối quan hệ giữa chúng.
Từ những gì tôi có thể nói, việc triển khai loại hệ thống đó sẽ đơn giản như một lớp MaterialNode với nhiều lớp con khác nhau (TextureNode, FloatNode, LerpNode, v.v.). Trong đó mỗi lớp con MaterialNode sẽ có MaterialConnections.
class MaterialConnection
{
MatNode_Out * fromNode;
MatNode_In * toNode;
}
class LerpNode : MaterialNode
{
MatNode_In x;
MatNode_In y;
MatNode_In alpha;
MatNode_Out result;
}
Đó là ý tưởng rất cơ bản , nhưng tôi hơi không chắc chắn về cách một vài khía cạnh của hệ thống này sẽ hoạt động:
1.) Nếu bạn xem các 'Biểu thức vật chất' (nút) khác nhau mà Unreal Engine 4 sử dụng , bạn sẽ thấy rằng mỗi loại có kết nối đầu vào và đầu ra của nhiều loại. Một số nút đầu ra nổi, một số vector2 đầu ra, một số vector4 đầu ra, v.v ... Làm cách nào tôi có thể cải thiện các nút và kết nối ở trên để chúng có thể hỗ trợ nhiều loại đầu vào và đầu ra? Liệu phân lớp MatNode_Out với MatNode_Out_Float và MatNode_Out_Vec4 (vân vân) có phải là một lựa chọn khôn ngoan?
2.) Cuối cùng, loại hệ thống này liên quan đến các shader GLSL như thế nào? Nhìn lại UE4 (và tương tự cho các hệ thống khác được liên kết ở trên), người dùng cuối cùng được yêu cầu cắm một số nút vật liệu vào một nút lớn với các tham số khác nhau đại diện cho các tham số shader (màu cơ bản, độ kim loại, độ bóng, độ phát xạ, v.v.) . Giả định ban đầu của tôi là UE4 có một loại 'shader chính' được mã hóa cứng với nhiều loại đồng phục khác nhau, và mọi thứ mà người dùng làm trong 'vật liệu' của họ chỉ đơn giản được chuyển cho 'shader chính' khi họ cắm các nút của họ vào ' nút chủ '.
Tuy nhiên, tài liệu UE4 nêu rõ:
"Mỗi nút chứa một đoạn mã HLSL, được chỉ định để thực hiện một tác vụ cụ thể. Điều này có nghĩa là khi bạn xây dựng Tài liệu, bạn đang tạo mã HLSL thông qua tập lệnh trực quan."
Nếu đó là sự thật, hệ thống này có tạo ra một kịch bản đổ bóng thực sự không? Làm thế nào chính xác để làm việc này?