Я пытаюсь обернуть вокруг головы , как материальные системы , как это , это реализуется. Эти мощные и удобные для пользователя графоподобные системы, по-видимому, довольно распространены как метод, позволяющий программистам и непрограммистам быстро создавать шейдеры. Однако из моего относительно ограниченного опыта в графическом программировании я не совсем уверен, как они работают.
Фон:
Поэтому, когда я ранее программировал простые системы рендеринга OpenGL, я обычно создаю класс Material, который загружает, компилирует и связывает шейдеры из статических файлов GLSL, которые я создал вручную. Я также обычно создаю этот класс как простую оболочку для доступа к унифицированным переменным GLSL. В качестве простого примера представьте, что у меня есть базовый вершинный шейдер и фрагментный шейдер с дополнительной равномерной Texture2D для передачи текстуры. Мой класс Material просто загрузит и скомпилирует эти два шейдера в материал, и с этого момента он предоставит простой интерфейс для чтения / записи формы Texture2D этого шейдера.
Чтобы сделать эту систему немного более гибкой, я обычно пишу ее так, чтобы я мог попытаться передать униформу любого имени / типа [т.е.: SetUniform_Vec4 ("AmbientColor", colorVec4); который установил бы униформу AmbientColor для конкретного 4d-вектора, называемого "colorVec4", если эта униформа существует в материале.] .
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, я хочу выровнять уровень. немного.
Вопрос:
Вот где я до сих пор, поэтому я пытался изучить, как другие движки рендеринга обрабатывают свои материальные системы.
Этот подход, основанный на узлах, великолепен и, похоже, является чрезвычайно распространенной системой для создания удобных для пользователя систем материалов в современных двигателях и инструментах. Из того, что я могу сказать, они основаны на структуре данных графа, где каждый узел представляет некоторый шейдерный аспект вашего материала, а каждый путь представляет собой какую-то связь между ними.
Из того, что я могу сказать, реализация системы такого типа была бы простым классом MaterialNode с множеством подклассов (TextureNode, FloatNode, LerpNode и т. Д.). Где каждый подкласс 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 , вы увидите, что каждое из них имеет входные и выходные соединения различных типов. Некоторые узлы выводят с плавающей точкой, некоторые выводят vector2, некоторые выводят vector4 и т. Д. Как я могу улучшить указанные выше узлы и соединения, чтобы они могли поддерживать различные типы ввода и вывода? Будет ли подклассы MatNode_Out с MatNode_Out_Float и MatNode_Out_Vec4 (и так далее) разумным выбором?
2.) Наконец, как эта система относится к шейдерам GLSL? Снова глядя на UE4 (и аналогично для других систем, связанных выше), пользователь должен в конечном итоге подключить некоторый узел материала к большому узлу с различными параметрами, которые представляют параметры шейдера (основной цвет, металличность, блеск, излучательная способность и т. Д.) , Мое первоначальное предположение заключалось в том, что в UE4 был какой-то жестко закодированный «мастер-шейдер» с различными формами, и все, что пользователь делает в своем «материале», просто передается «мастер-шейдеру», когда они подключают свои узлы к « мастер-узел ».
Однако в документации UE4 говорится:
«Каждый узел содержит фрагмент кода HLSL, предназначенный для выполнения конкретной задачи. Это означает, что когда вы создаете материал, вы создаете код HLSL с помощью визуальных сценариев».
Если это правда, генерирует ли эта система настоящий шейдерный скрипт? Как именно это работает?