2

编辑: 我将 GLTextureUnitID 从 uint 更改为 int,它导致错误停止出现,但呈现黑色方块而不是纹理。当我注释掉对 SetTexture 的调用时,即使我从未在该行之前设置过该制服,它仍然可以正常呈现。

Edit2: 看起来 GLTextureUnitID 的值为 1,而正在设置的纹理的 ID 为 0。

Edit3: 将 SetTexture 函数更改为具有以下内容似乎已经解决了问题,但感觉有点像一个肮脏的解决方案。

GL.BindTexture(TextureTarget.Texture2D, (int)texture.GLTextureUnitID);
GL.Uniform1(GLTextureUnitLocation, 0);

原始问题: 我开始在我的项目中添加对纹理文件的支持,但是每当我为我的纹理着色器程序调用 GL.Uniform1 时,我都会收到“InvalidOperation”错误。更奇怪的是,当我注释掉对导致错误的函数的调用时,纹理仍然会被渲染。

渲染带有纹理的四边形的 RenderGUI 函数是:

    public override void RenderGUI()
    {
        // Translate Matrix to Position of GUI Element
        Matrices.Translate(SetMatrixParam.ModelViewMatrix, Position.X, Position.Y, 0);

        // Bind Shaders and Send Matrices
        Shader.Bind();
        Shader.SendMatrices();

        // Set Texture Information
        Shader.SetTexture(Texture); // <- This causes the error, it's just a call to Uniform1 using a property from the texture object, if commented out the error doesn't appear.
        Shader.SetTextureColor(Color4.White);

        GL.Begin(BeginMode.Triangles);

        // Render Quad
        Vector3 topLeft = new Vector3(0, 0, 0);
        Vector3 bottomLeft = new Vector3(0, Size.Y, 0);
        Vector3 topRight = new Vector3(Size.X, 0, 0);
        Vector3 bottomRight = new Vector3(Size.X, Size.Y, 0);

        Shader.SetTextureCoord(0, 0); GL.Vertex3(topLeft); // Top Left
        Shader.SetTextureCoord(0, 1); GL.Vertex3(bottomLeft); // Bottom Left
        Shader.SetTextureCoord(1, 1); GL.Vertex3(bottomRight); // Bottom Right

        Shader.SetTextureCoord(0, 0); GL.Vertex3(topLeft); // Top Left
        Shader.SetTextureCoord(1, 1); GL.Vertex3(bottomRight); // Bottom Right
        Shader.SetTextureCoord(1, 0); GL.Vertex3(topRight); // Top Right

        GL.End();
    }

并且正在调用的函数导致出现错误:

    public void SetTexture(Texture2D texture)
    {
        if (texture.GLTextureUnitID == null)
            throw new ArgumentException();

        GL.Uniform1(GLTextureUnitLocation, (uint)texture.GLTextureUnitID);
    }

这也可以在这个项目的 github 上找到。连同Texture2D 类以及正在使用的顶点片段着色器以及处理使用这些着色器的着色器程序的类。

4

2 回答 2

1

为了将纹理绑定到程​​序的统一插槽,您需要:

  1. 从 glGenTextures 返回的纹理的 gl-name
  2. 从 glGetUniformLocation 返回的统一位置
  3. 用于绑定纹理的纹理单元(应由您的系统决定;通常取决于绑定到着色器需要多少纹理)

在您的纹理类中,我认为您混淆了纹理单元和 gl-name。

以下是纹理绑定的伪代码

Int32 texunit = 0; // assume your shader only have 1 texture-type uniform
Shader.Bind();
GL.Uniform1( Shader.GetUniformLocation( "uniformName" ), texunit );
GL.ActiveTexture( texunit );
GL.BindTexture( TextureTarget.Texture2D, (int)tex.GLTextureUnitID ); // I recommend renaming tex.GLTextureUnitID to tex.GLName

希望这可以帮助

于 2013-06-26T07:47:31.537 回答
1

有错误的代码在哪里?

http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml有一个 glUniform1 会返回 GL_INVALID_OPERATION 的原因列表。我建议您仔细检查每一个并自己确认它适用或不适用。

这是列表:

错误

如果没有当前程序对象,则生成 GL_INVALID_OPERATION。

如果着色器中声明的统一变量的大小与 glUniform 命令指示的大小不匹配,则会生成 GL_INVALID_OPERATION。

如果此函数的有符号或无符号整数变体之一用于加载 float、vec2、vec3、vec4 类型的统一变量或这些变量的数组,或者此函数的浮点变体之一,则会生成 GL_INVALID_OPERATION用于加载 int、ivec2、ivec3、ivec4、unsigned int、uvec2、uvec3、uvec4 或这些类型的数组的统一变量。

如果此函数的有符号整数变体之一用于加载 unsigned int、uvec2、uvec3、uvec4 或这些类型的数组的统一变量,则会生成 GL_INVALID_OPERATION。

如果此函数的无符号整数变体之一用于加载 int、ivec2、ivec3、ivec4 或这些类型的数组的统一变量,则会生成 GL_INVALID_OPERATION。

如果 location 是当前程序对象的无效统一位置并且 location 不等于 -1,则生成 GL_INVALID_OPERATION。

如果 count 大于 1 并且指示的统一变量不是数组变量,则生成 GL_INVALID_OPERATION。

如果使用 glUniform1i 和 glUniform1iv 以外的命令加载采样器,则会生成 GL_INVALID_OPERATION。

于 2013-06-24T14:32:35.967 回答