在基于图的材料系统中,如何支持各种输入和输出类型?


11

在此处输入图片说明

我想换我的头周围怎么样材料系统这样这个实现。这些功能强大且用户友好的,类似于图形的系统作为允许程序员和非程序员都可以快速创建着色器的方法,似乎相对普遍。但是,从我相对有限的图形编程经验来看,我不太确定它们是如何工作的。


背景:

因此,当我之前对简单的 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代码。”

如果是这样,此系统是否生成真实的着色器脚本?这是如何工作的?


1
与您的问题有关:gameangst.com/?p=441
glampert 2014年

Answers:


10

我将尽我所能来回答问题,对UE4的具体情况了解甚少,而只是对一般技术的了解。

基于图的材料和自己编写代码一样,都是程序设计。对于没有代码背景的人来说,它似乎并不喜欢它,这使它看起来更容易。因此,当设计人员链接“添加”节点时,他基本上是在编写add(value1,value2)并将输出链接到其他对象。这就是它们的含义,即每个节点将生成HLSL代码,无论是函数调用还是简单的指令。

最后,使用材质图就像使用预定义函数库对原始着色器进行编程,这些函数可以执行一些常见的有用操作,这也是UE4所做的。它具有一个着色器代码库,适用时着色器编译器将使用该库并将其注入最终的着色器源。

对于UE4,如果他们声称将其转换为HLSL,我假设他们使用的转换工具可以将HLSL字节码转换为GLSL字节码,因此可以在GL平台上使用。但是其他库仅具有多个着色器编译器,它们将读取图形并直接生成所需的着色语言源。

材质图也是从平台细节中进行抽象并从艺术指导的角度关注重要内容的一种好方法。由于它不受语言和更高级别的约束,因此它更容易针对目标平台进行优化,并将动态代码(如光照处理)动态地注入到着色器中。

1)现在,为了更直接地回答您的问题,您应该采用数据驱动的方法来设计这样的系统。查找一种可以用非常简单的结构定义甚至可以在文本文件中定义的平面格式。本质上,每个图应该是节点数组,具有类型,一组输入和输出,并且每个字段都应具有本地link_id以确保图连接是明确的。同样,这些字段中的每个字段都可以具有该字段支持的其他配置(例如,支持什么类型的数据类型)。

使用这种方法,您可以轻松地将节点的字段定义为(float | double),并让其从连接中推断类型,或将其强制插入其中,而无需类层次结构或过度设计。您可以根据需要将图形数据结构设计为刚性还是柔性。您需要做的就是拥有足够的信息,以便代码生成器不会产生歧义,因此可能会处理您想做的事情。重要的是,在基本数据结构级别上,您应保持灵活性并专注于解决仅定义材料的任务。

当我说“定义材料”时,我非常特别地指的是定义一个网格表面,而不是几何本身提供的。这包括使用其他顶点属性来配置表面的外观,使用高度图为其添加位移,使用每个像素的法线干扰法线,更改基于物理的参数,更改BRDF等等。您不想描述任何其他东西,例如HDR,色调映射,蒙皮动画,灯光处理或在着色器中完成的许多其他事情。

2)然后由渲染器的着色器生成器遍历此数据结构,并通过读取其信息来组装一组变量,并使用预制函数将它们链接在一起,并注入计算照明和其他效果的代码。请记住,着色器不仅会因不同的图形API不同而有所不同,而且在不同的渲染器之间也有所不同(延迟渲染与基于图块的渲染与正向渲染器都需要不同的着色器才能工作),并且使用这样的材质系统,您可以从讨厌的对象中抽象出来低层,只专注于描述表面。´

对于UE4,他们提出了您提到的最终输出节点的清单,他们认为该清单描述了旧游戏和现代游戏中99%的表面。他们几十年来开发了这组参数,并用Unreal引擎到目前为止制作的大量游戏证明了这一点。因此,如果您以与虚幻相同的方式进行操作,您会很好。

总结一下,我建议使用一个.material文件来处理每个图形。在开发期间,它可能包含基于文本的格式以进行调试,然后将其打包或编译为二进制以进行发布。每个.material将由N个节点和N个连接组成,就像SQL数据库一样。每个节点将具有N个字段,其中包含一个名称和一些接受类型的标志(如果其输入或输出,推断类型等)。用于保存加载的材料的运行时数据结构将是平坦而简单的,因此编辑器可以轻松调整它并保存回文件。

然后将实际的繁重工作留给最终的着色器生成,这确实是最难的部分。美丽的部分是您的材质与渲染平台无关,从理论上讲,只要您以适当的着色语言表示材质,它就可以与任何渲染技术和API一起使用。

让我知道您是否需要其他详细信息或答案中的任何修正,我丢失了所有文本的概述。


非常感谢您编写如此详尽而出色的答案。我觉得我对应该从这里出发应该有个好主意!谢谢!
MrKatSwordfish 2014年

1
伙伴们,没问题,如果您需要其他帮助,请随时与我联系。我实际上是在为自己的工具开发类似的东西,所以如果您想交流思想,请成为我的客人!祝您下午愉快:D
Grimshaw 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.