1

我需要统一名称的最大长度。即:给定一个带有制服的用过的程序uniform testuniform 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)。

glGetProgramivwithGL_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);
    }
}
4

2 回答 2

1

您发现了一个驱动程序错误。您可以尝试报告它(这个论坛是一个可以看到它的地方),但您无法使其正常工作。所以只是解决它。

而不是只有一个最大尺寸,只需依次询问每个制服的长度是多少。在 C/C++ 中,您可以通过将缓冲区的 NULL 传递给glGetActiveUniformName

GLsizei length;
glGetActiveUniformName(program, index, 1000 /*large number*/, &length, NULL);
//Use length to allocate a buffer of the appropriate size.

我不知道这将如何使用 JOGL。也许您应该切换到 LWJGL,它对该函数有更合理的 Java 实现。

此外,停止将字符串存储为字节数组。将它们转换为正确的 Java 字符串(使用 LWJGL 的另一个原因)。

于 2012-09-23T19:24:06.330 回答
0

我们确实遇到了这个问题,我已经看到其他人在这里描述过它:

http://www.opengl.org/discussion_boards/showthread.php/179117-Driver-bug-causing-incorrect-glGetProgramiv-output

就我而言,问题是在各种 GPU 型号中从 nvidia 295.40 驱动程序升级到 304.64 后出现的。在上面的那个论坛中,报告了英特尔驱动程序的错误 ¿ 您使用的是哪个驱动程序 Ludowijk ?

我想也许以“gl_”开头的内置属性不考虑用于最大名称长度计算,但即使这是真的,恕我直言,这种行为应该被视为一个错误。

感谢 Nicol 提出解决方法的想法。

于 2012-11-14T09:55:46.567 回答