我想换我的头周围怎么样材料系统这样,这个实现。这些功能强大且用户友好的,类似于图形的系统作为允许程序员和非程序员都可以快速创建着色器的方法,似乎相对普遍。但是,从我相对有限的图形编程经验来看,我不太确定它们是如何工作的。
背景:
因此,当我之前对简单的 OpenGL渲染系统进行编程时,通常会创建一个Material类,该类从我手动创建的静态GLSL文件中加载,编译和链接着色器。我通常还将此类创建为访问GLSL统一变量的简单包装。举一个简单的例子,假设我有一个基本的顶点着色器和片段着色器,并带有一个额外的均匀Texture2D用于传递纹理。我的Material类将简单地将这两个着色器加载并编译到材质中,从那时起,它将公开一个简单的接口来读取/写入该着色器的Texture2D制服。
为了使该系统更具灵活性,我通常以一种允许我尝试传递任何名称/类型的制服的方式编写它(即:SetUniform_Vec4(“ AmbientColor”,colorVec4); 如果材质中存在均匀的AmbientColor统一矢量,该矢量将被称为“ 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类的客户必须仅凭信心访问制服,因此感觉就像是一个糟糕的系统- 用户必须有点了解每个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使用的各种“材料表达式”(节点),您会发现它们各自具有各种类型的输入和输出连接。一些节点输出浮点数,一些输出vector2,一些输出vector4,等等。如何改善上面的节点和连接,以便它们可以支持各种输入和输出类型?明智的选择是用MatNode_Out_Float和MatNode_Out_Vec4(依此类推)对MatNode_Out进行子类化吗?
2.)最后,这种系统与GLSL着色器有何关系?再次查看UE4(和上面链接的其他系统类似),要求用户最终将一些材质节点插入具有各种参数的大型节点,这些参数代表着色器参数(基础颜色,金属度,光泽度,发射率等)。 。我最初的假设是,UE4具有某种带有各种制服的硬编码“主着色器”,并且用户将其节点插入“主着色器”时,用户在其“材质”中所做的所有操作都将简单地传递给“主着色器”。主节点”。
但是,UE4文档指出:
“每个节点都包含一个指定执行特定任务的HLSL代码片段。这意味着在构造材料时,您正在通过可视脚本创建HLSL代码。”
如果是这样,此系统是否生成真实的着色器脚本?这是如何工作的?