OpenGL每网格材质(着色器)

时间:2018-09-26 08:54:30

标签: c++ opengl rendering game-engine fragment-shader

因此,我正在使用C ++和OpenGL 4开发一个简单的游戏引擎。现在,我正在努力处理导入的模型。

我正在使用FBX sdk,通过一种非常幼稚的方法来导入fbx模型:基本上,我访问了fbx的每个节点,并将网格数据附加到单个大型结构中,该结构随后用于渲染。但是,我希望能够为模型使用的每种材质指定不同的片段着色器(例如,为汽车轮辋和灯光使用不同的着色器)。

作为参考,UE4的材质系统允许用户使用类似蓝图的编辑器定义简单的着色器。

我想对引擎应用类似的概念,允许创建一个材质对象,该对象指定一段片段着色器代码和一组要使用的纹理。

我面临的问题是:

  1. 很明显,我必须为使用不同材料的每个模型零件分开绘制调用,因为我不能在绘制调用中间交换程序(可以吗?):在这一点上,最好有每个零件单独的vao / vbo / ebo或单个零件,并跟踪零件的结束位置和下一个零件的开始位置? (我猜这是最好的选择)
  2. 仅预编译着色器片段并将其动态附加到当前程序(例如glAttach + glLinkProgram + glUseProgram)是一种好习惯,还是考虑到每种材质预先链接整个程序更好?顶点着色器总是相同的?

1 个答案:

答案 0 :(得分:1)

  1. 否,您不能在绘图调用过程中更改程序。对于基于数据布局的GPU表现如何,存在不同的意见和测试。我的经验是,如果您不打算在第一次上传网格数据后修改网格数据,最有效的方法是使用一个VAO,其中包含两个VBO:一个用于索引,另一个用于其余数据。发出绘制调用时,您将根据网格数据(应跟踪)偏移索引缓冲区,并偏移着色器属性的配置。由于内存块是连续的,因此这种方法允许更友好的缓存和更有效的内存访问。但是,正如我所提到的,在某些情况下,这将不是最有效的方法(尽管我相信它仍然足够有效)。这取决于您的硬件和驱动程序。

  2. 在启动渲染循环之前预编译并链接所有程序。它是最有效的方法

另外,我建议您研究一下UBER着色器技术。此方法基于为不同的可能输入创建着色器,并创建一组defines或子例程体系结构,该体系结构允许您编译同一着色器的不同版本(例如,您可能具有常规纹理,您可能要应用凹凸贴图,但其他模型可能没有此纹理,因此执行完全相同的着色器将导致不确定的行为或崩溃。