为什么在设置uniform变量之前我必须“使用”着色器程序?

6
我正在使用C++和GLSL 410中的OpenGL 4.5。
最近我遇到了一个问题,我试图在没有使用glUseProgram与着色器程序之前设置着色器程序的统一变量。 我有一个包含名为input_color的统一变量(一个vec4,我将输出颜色设置为它)的片段着色器附加到我的shader_program上。请注意,在绘制任何应使用它的内容之前,我会在主绘制循环中调用glUseProgram(shader_program)
// set uniforms
GLint input_color = glGetUniformLocation(shader_program, "input_color");
glUniform4f(input_color, 0.5f, 0.3f, 0.2f, 1.0f);

使用该程序绘制的三角形全为黑色,与我预期的结果不同。经过一些尝试,我意识到在设置统一变量之前需要使用该程序。
// set uniforms
glUseProgram(shader_program); // my change
GLint input_color = glGetUniformLocation(shader_program, "input_color");
glUniform4f(input_color, 0.5f, 0.3f, 0.2f, 1.0f);

绘制结果呈现正确颜色的三角形。
我的问题是为什么我需要先启动程序?我知道OpenGL作为状态机,但在这种情况下,为什么当前着色器程序状态是必要的?毕竟,我明确将着色器程序索引作为参数传递给glGetUniformLocation以获取input_color的内存索引。
我希望这个答案能帮助我更好地理解OpenGL中的状态以及GPU中表示着色器程序的内存块是如何被利用或管理的。

"OpenGL 4.5 in C++ and GLSL 410." 为什么要使用GLSL 4.10的4.5版本?不能使用GLSL 4.50吗? - Nicol Bolas
我一直在使用的指南有点过时,它们规定了4.10版本。我会开始使用4.50版本。 - Rob
1个回答

8

您不必这样做。GL 4.1及以上版本提供了glProgramUniform(),它接受您要修改的程序对象。


1
谢谢 - 我不知道这个选项的存在。那么,可以这样说 glUniform 只能通过查看“正在使用”的程序来定位内存中的程序,而 glProgramUniform 具有不同程序索引的参数吗? - Rob
2
是的,这就是OpenGL一直以来(历史上)采用的“绑定使用”或“绑定修改”方法的全部意义所在。幸运的是,OpenGL开始转向直接接受要修改的对象的函数,而不是绑定方式。这在OpenGL 4.5中通过采用ARB_direct_state_access扩展得到了充分实现。请参见https://www.khronos.org/opengl/wiki/Direct_State_Access。 - peppe
1
我晚了3年,但仍想知道作者问题的答案。我明白从GL 4.1开始,我们在修改uniform之前不必使用glUseProgram(),但问题仍然存在,为什么在GL 4.1之前的版本中这是必需的步骤? - A. Khaled
@A.Khaled:因为API就是这样编写的。 - Nicol Bolas
2
@A.Khaled 在这里,“使用程序”就像“绑定纹理”一样,只需要在操作该OpenGL对象之前完成即可。 - LegendLength

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接