使用统一缓冲区(即D3D语言中的常量缓冲区)。
只要您所有的着色器都同意每个这样的缓冲区的布局和绑定点,那么更新就变得轻而易举。模型完全不需要了解着色器。他们只需要在其常量缓冲区中更新模型视图矩阵,渲染管道就会自动使用它。
至少我认为您应该有两个这样的缓冲区。第一个应该存储您的投影矩阵,摄影机矩阵,串联的摄影机-投影矩阵,视口信息,平截头体细节和矩阵逆。每个场景只需更新一次该缓冲区。
然后为每个模型提供另一个缓冲区,以存储其模型视图矩阵,法线矩阵,逆和材质属性。每个模型都会对此进行一次更新,并且可以通过不同的更新过程(如果适用)来完成。如果您能够在多个对象之间共享材料,则可以/应该将材料信息移至第三个特定于材料的缓冲区。
在前向阴影设置中,将所有光源放置在另一个缓冲区中是有意义的,而在延迟阴影中,同样使用每个光源的缓冲区进行光照是有意义的(代替模型中使用的模型/材质缓冲区)。几何传递)。
请注意,您需要一个适度最新的GL版本,才能完全使用统一的缓冲区(3.1或扩展名;除了一些较旧但仍在使用中的笔记本电脑外,今天已经足够通用),并且需要一个相当新的版本能够从着色器代码内部将统一的缓冲区绑定到特定的绑定位置(4.2;仍然不常见,但是会变得更好),否则您必须在CPU端代码中做更多的工作来进行设置(您的CPU代码需要知道正确的绑定)还是要指出点,所以它更多的是API气味,而不是严重的问题)。不幸的是,OpenGL | ES直到3.0才添加统一缓冲区,但大多数流行的移动平台仍不支持该缓冲区。
如果没有选择缓冲区,那么您将需要一些全局位置来存储活动着色器的索引位置。您可以glGetUniformLocation
在加载着色器后使用它来查找知名名称(如ModelViewMatrix
或类似名称)的索引,然后存储这些索引。您的渲染器可以映射枚举值,例如MODEL_VIEW
传递给SetUniform
包装函数的值,以查看绑定的着色器,找到索引并glUniform
正确调用。客户端代码对缓冲区的使用并没有特别大的改变,除非您将每个统一包装得很好,否则需要分别设置每个统一。
请参见GLSL接口块和统一缓冲区对象。