我需要统一名称的最大长度。即:给定一个带有制服的用过的程序uniform test
,uniform myuniform
应该glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, outParam)
得到10的输出(对于“myuniform”)。
我有一个非常简单的测试着色器,设置了 1 个定义的统一:uniform float time
glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, outParam)
返回 5,即 的长度time
。如果我将“时间”更改为其他内容,它会返回更改后的长度(例如:更改为“计时器”会返回 6)。
glGetProgramiv
withGL_ACTIVE_UNIFORMS
告诉我有 2 套制服。它报告的第二个制服是 gl_ModelViewProjectionMatrix。
我对它在列表中包含 gl_ModelViewProjectionMatrix 很好 - 我在着色器中使用它,但是当与其他返回值结合使用时会出现问题。如果 glGetProgramiv 包含在列表中,为什么不返回“gl_ModelViewProjectionMatrix”的长度?我需要我的应用程序的属性和变量的全名,但由于我的最大长度为 5,glGetActiveUniform
因此返回了一个不可接受的统一名称“gl_M”。
最大名称长度应该包括 MVP 矩阵,或者名称列表不应该。将名称包含在列表中但不包含在最大名称长度计算中是没有意义的。
这只发生在我身上吗?我用谷歌找不到任何关于它的东西。我可以放弃对最大长度的查询并始终使用非常大的缓冲区,但我以前见过一些非常长的变量名,因此缓冲区必须很大才能保证没有错误。无论如何,这不是一个真正的解决方案。
此测试对属性正常工作。我使用 gl_Vertex 并且没有其他属性。系统正确报告了 1 个当前属性,长度为 10,名称为 gl_Vertex。如果我完全移除我的时间制服,那么 MVP 矩阵将成为唯一使用的制服,系统会报告 1 个当前制服,最大名称长度为 0,因此使用返回的最大长度获取其名称将一无所获。
为了完整起见,我包括下面的代码。该代码使用 Java 编写,并使用 JOGL 访问 OpenGL 绑定。为了突出相关区域,我删除了与此问题无关的行,主要是 GUI 更新,包括实际显示此处获得的值的 GUI 部分。如上所述,我还删除了获取属性的部分,因为它工作正常。
仅供对 Java 主义持谨慎态度的 C 人参考:将 Buffer ( IntBuffer
, ByteBuffer
, ) 想象为FloatBuffer
指针、buffer.get()
likebuffer[n++]
和. 我还在 C 和 C++ 中使用 OpenGL,所以如果这里的 GLSL 专家更喜欢,我可以用 C 重写它。buffer = IntBuffer.allocate(n)
malloc()
有什么建议么?
// add options to panelShaderParameters
public void updateShaderParameters(GLAutoDrawable surface)
{
GL2 gl = surface.getGL().getGL2();
IntBuffer outParam = IntBuffer.allocate(1);
int numParameters = 0,
maxNameLength = 0;
IntBuffer size = null,
type = null;
ByteBuffer name = null;
gl.glGetProgramiv(shader.getName(), GL2.GL_ACTIVE_UNIFORMS, outParam);
numParameters = outParam.get();
outParam = IntBuffer.allocate(1);
gl.glGetProgramiv(shader.getName(), GL2.GL_ACTIVE_UNIFORM_MAX_LENGTH, outParam);
maxNameLength = outParam.get();
for(int i = 0; i < numParameters; i += 1)
{
size = IntBuffer.allocate(1);
type = IntBuffer.allocate(1);
name = ByteBuffer.allocate(maxNameLength);
gl.glGetActiveUniform(shader.getName(), i, maxNameLength, (IntBuffer)null, size, type, name);
byte[] nameBuffer = new byte[maxNameLength];
name.position(0);
name.get(nameBuffer);
}
}