Reputation: 197
Edit: I changed GLTextureUnitID from a uint to an int, and it caused the error to stop appearing, but instead of the texture, a black square renders. When I comment out the call to SetTexture it still renders fine even though I never set that uniform before that line.
Edit2: It appears GLTextureUnitID has a value of 1, while the texture that is being set has an ID of 0.
Edit3: Changing the SetTexture function to have the following seems to have solved the problem, but it feels like a bit of a dirty solution.
GL.BindTexture(TextureTarget.Texture2D, (int)texture.GLTextureUnitID);
GL.Uniform1(GLTextureUnitLocation, 0);
Original Question: I started adding support for texture files to my project but whenever I call GL.Uniform1 for my textured shader program, I get an "InvalidOperation" error. Ever stranger, when I comment out the call to the function that causes the error, the texture still gets rendered.
The RenderGUI function in which the quad with a texture is being rendered is:
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();
}
And the function that's being called that's causing an error to appear:
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. along with the Texture2D class and the vertex and fragment shader being used and the class handling the shader program that uses those shaders.
Upvotes: 3
Views: 1942
Reputation: 69
In order to bind a texture to a program's uniform slot, you will need:
In your texture class, I think you have mixed up the texture-unit and the gl-name.
And the followings is the pseudo code for texture binding
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
Hope this helps
Upvotes: 1
Reputation: 2312
Where is the code with the error?
From http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml there is a list of many reasons why glUniform1 would return an GL_INVALID_OPERATION. I'd suggest just going through each one and confirming for yourself that it either applies or does not apply.
Here's the list:
Errors
GL_INVALID_OPERATION is generated if there is no current program object.
GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.
GL_INVALID_OPERATION is generated if one of the signed or unsigned integer variants of this function is used to load a uniform variable of type float, vec2, vec3, vec4, or an array of these, or if one of the floating-point variants of this function is used to load a uniform variable of type int, ivec2, ivec3, ivec4, unsigned int, uvec2, uvec3, uvec4, or an array of these.
GL_INVALID_OPERATION is generated if one of the signed integer variants of this function is used to load a uniform variable of type unsigned int, uvec2, uvec3, uvec4, or an array of these.
GL_INVALID_OPERATION is generated if one of the unsigned integer variants of this function is used to load a uniform variable of type int, ivec2, ivec3, ivec4, or an array of these.
GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1.
GL_INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable.
GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv.
Upvotes: 2