GLSL设置纹理单元均匀问题

时间:2013-06-24 13:44:51

标签: opengl graphics shader opentk

修改 我将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);
    }

This can also be found at the github for this project.以及正在使用的Texture2D classvertex以及fragment着色器以及class handling the shader program that uses those shaders

2 个答案:

答案 0 :(得分:1)

带错误的代码在哪里?

http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml开始,列表中列出了glUniform1返回GL_INVALID_OPERATION的原因。我建议你仔细检查每一个并确认它是适用还是不适用。

以下是清单:

  

错误

     

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

     

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

     

如果签名或未签名之一,则生成GL_INVALID_OPERATION   此函数的整数变体用于加载统一变量   类型为float,vec2,vec3,vec4或这些类型的数组,或者如果其中之一   此函数的浮点变体用于加载均匀   int,ivec2,ivec3,ivec4,unsigned int,uvec2,uvec3类型的变量,   uvec4,或其中的数组。

     

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

     

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

     

如果location是无效的制服,则会生成GL_INVALID_OPERATION   当前程序对象和位置的位置不等于   -1

     

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

     

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

答案 1 :(得分:1)

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

  1. 从glGenTextures
  2. 返回的纹理的gl-name
  3. 从glGetUniformLocation
  4. 返回的统一位置
  5. 用于绑定纹理的纹理单元(应由您的 系统;通常取决于绑定到着色器需要多少纹理)
  6. 在你的纹理类中,我认为你混淆了纹理单元和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
    

    希望这有帮助