I'm writing a 2D game in OpenTK, using OpenGL 4.4. Using colour and texture UV coordinates and a matrix I can succesfully draw textures between vertices with vertex shader:
public const string vertexShaderDefaultSrc = @" #version 330
uniform mat4 MVPMatrix;
layout (location = 0) in vec2 Position;
layout (location = 1) in vec2 Texture;
layout (location = 2) in vec4 Colour;
out vec2 InTexture;
out vec4 OutColour;
void main()
{
gl_Position = MVPMatrix * vec4(Position, 0, 1);
InTexture = Texture;
OutColour = Colour;
}";
and fragment shader:
public const string fragmentShaderDefaultSrc =
@"
#version 330
uniform sampler2D Sampler;
in vec2 InTexture;
in vec4 OutColour;
out vec4 OutFragColor;
void main()
{
OutFragColor = texture(Sampler, InTexture) * OutColour;
//Alpha test
if(OutFragColor.a <= 0)
discard;
}
";
BUT if I want to draw just a solid colour rather than a texture, I use this shader (with the same vertices, passing UV coords that won't be used):
public const string fragmentShaderSolidColourSrc =
@"
#version 330
uniform sampler2D Sampler;
in vec2 InTexture;
in vec4 OutColour;
out vec4 OutFragColor;
void main()
{
OutFragColor = OutColour;
//Alpha test
if(OutFragColor.a <= 0)
discard;
}
";
Now this works beautifully, but OpenGL reports an error - GL_INVALID_VALUE. It draws fine and everything seems to work, but ideally I would like OpenGL to be error free in that situation, so I can catch real errors. I would appreciate any help, and can share more detail of how the shader is compiled or used if that is helpful - what I don't understand is how the default shader can work but the solid colour doesn't.
I have tracked down the exact source of the errors in my render call (shader builds with no problems)
GL.EnableVertexAttribArray(shader.LocationPosition);
GL.VertexAttribPointer(shader.LocationPosition, 2, VertexAttribPointerType.Float, false, Stride, 0);
//-----everything up to here is fine
//this line throws an error
GL.EnableVertexAttribArray(shader.LocationTexture);
//as does this line
GL.VertexAttribPointer(shader.LocationTexture, 2, VertexAttribPointerType.Float, false, Stride, 8);
//this is all ok
GL.EnableVertexAttribArray(shader.LocationColour);
GL.VertexAttribPointer(shader.LocationColour, 4, VertexAttribPointerType.UnsignedByte, true, Stride, 16);
//ok
GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer);
GL.DrawArrays(DrawType, 0, Vertices.Length);
//ok
GL.DisableVertexAttribArray(shader.LocationPosition);
//this line throws error
GL.DisableVertexAttribArray(shader.LocationTexture);
//this is ok
GL.DisableVertexAttribArray(shader.LocationColour);
It appears to me after some tests (would be nice to have this verified) that if a variable such as the texture coordinates are not used by the shader the compiler gets rid of it, so a call to get it's location returns -1. Simply checking if locationTexture was -1 here and then not binding locationTexture etc if so resolved my issues.