我应该如何使用opengl组织着色器系统

我在考虑:

有一个主要着色器将应用于我的应用程序的每个对象,它将用于投影,转换,定位,着色等.

并且每个对象可以有额外的着色器用于额外的东西,例如水对象肯定需要额外的着色器.

但是有一个问题,我如何将2个或更多着色器应用到一个对象中?因为我需要应用主着色器对象自己的着色器.

最佳答案 如果OpenGL(或Direct3D!)允许你在每个顶点/片段/任何阶段拥有多个着色器,那将是非常好的,但是我们仍然坚持使用现有系统.

假设你已经写了一堆GLSL函数.有些是所有对象的通用目的,例如应用模型视图转换和将纹理坐标复制到下一个阶段.有些特定于特定类别的对象,例如水或岩石.

然后你写的是ubershader,一个程序,其中vertex / fragment /中的main()函数除了调用所有这些函数之外什么都不做.这是一个模板或原型,您可以从中生成更专业的程序.

最常见的方法是在main()内部使用预处理器和大量#ifdefs函数调用.也许如果您在没有任何#defines的情况下进行编译,您将获得标准变换和Gouraud着色.添加#define WATER以获得水效果,#define DISTORT用于某种自由形态变形算法,如果你想要自由形态变形水,#define FOG添加雾效果,…

您甚至不需要拥有ubershader源的多个副本,因为您可以在运行时生成#define字符串并将它们传递给glCompileShader.

你最终得到的是很多着色器程序,每种类型的渲染都有一个.如果由于任何原因你宁愿只有一个程序,你可以在新的系统上用GLSL子程序做类似的事情.

这些基本上都是GLSL中的函数指针,你可以像制服一样设置它们.现在你的ubershader在main()函数中有1,2,…函数指针调用.你的程序只设置#1为标准变换,#2为摇滚/水/无论如何,#3为雾,…如果您不想使用舞台,只需拥有NOP功能即可分配.

虽然这具有仅使用一个程序的优点,但它不像#define方法那样灵活,因为任何给定的指针都必须使用相同的函数原型.如果说WATER需要在多个着色器中进行处理,那么它也会更加有用,因为你必须记住在每个着色器中设置函数指针而不是只有一个#define.

希望这可以帮助.

点赞