GLSL 有许多预定义的全局变量,例如
gl_LightSource
。它们是全局的,因为任何着色器都可以访问它们。
如何在 GLSL 中定义自定义全局变量?
GLSL 中不存在全局变量。
gl_*
变量是硬编码变量(将它们视为自动添加的编译时),用于从着色器访问管道的不可编程元素。在 Core OpenGL 3.0 中,大部分内容被删除,包括 gl_LightSource
。现在,用户需要处理自己的矩阵和灯光,并将它们作为制服发送到着色器。有关完整列表,请参阅 内置变量 (GLSL) wiki。
你想要的是制服。如果您想在着色器之间同步制服,请存储制服的位置并迭代所有程序以将制服上传到每个着色器。
您可以使用统一缓冲区。这是一个教程:http://www.lighthouse3d.com/tutorials/glsl-tutorial/uniform-blocks/
OpenGL 中的全局着色器变量称为“uniforms”。它们是只读的,可以与
glUniformX
调用绑定。粗略地说,它看起来像这样(这更像是伪代码):
// 1. activate the program
glUseProgram(program)
// 2. get uniform location
foo = glGetUniformLocation(program, "foo")
// 3. bind the value, e.g. a single float
glUniform1f(foo, 42.0)
在着色器中,您需要使用
uniform
存储限定符来限定变量,例如
uniform float foo;
持久变量的实用性绝对是值得追求的。 OpenGL 在 gl3 中引入了实例化,但实际上是在 gl4 中完全建模的。此答案的目的是扩展其他答案并介绍实例 VBO。
如果您有权访问 gl4,则可以保持实例化 VBO 加载可以在每次绘制(而不是每个顶点)时更改的数据(如果它用于平铺地图等内容)。您可以利用 GLSL 变量
gl_InstanceID
来检测您正在进行哪个绘图调用。
在平铺地图的情况下,您使用一个模型(可能是 2 个三角形,即 4 个点、4 个纹理坐标、6 个索引形成一个四边形)来渲染大量平铺。您可以使用普通的 gl 缓冲区函数轻松地在 cpu 端更新所述 VBO 的值。 VBO 可以保存类似于tileid 的内容,它可以帮助您计算索引指定图块的图块表的纹理坐标。好处是它会按实例更新。
“在抽奖之间保存变量”的典型用例通常归结为需要一个计数器,而
gl_InstanceID
绝对符合要求。除非您需要 GPU 执行需要保存回来的操作。
如果您想要在 GPU 上进行计算,那么 UBO 是从 GLSL 着色器获取数据或从 GLSL 着色器获取数据的一种非常好的方法。正如@Arne 所建议的。但是,可能有某种方法使用其他方法来完成您想要做的事情,并且在一般使用中应该避免它们,除非您实际上使用了很多统一变量。
如果你想定义一个常量变量,你可以使用const关键字。但是,这在着色器之间不会持续存在。仅定义它的着色器。
const float example = 5.0;