0
votes

I want to draw a colored triangle in OpenTK using a simple fragment shader with a fixed output color. However, the triangle always stays white. What causes this problem?

Here is the init and render code:

game.Load += (sender, e) =>
{
    game.VSync = VSyncMode.On;

    float[] vertexPositions = {
        0.75f, 0.75f, 0.0f, 1.0f,
        0.75f, -0.75f, 0.0f, 1.0f,
        -0.75f, -0.75f, 0.0f, 1.0f,
    };

    GL.GenBuffers(1, out vbo);
    GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
    GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(
        vertexPositions.Length * sizeof(float)), vertexPositions, BufferUsageHint.StaticDraw);
    GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

    // load shaders, create and link shader program
    string shaderPath = @"K:\VisualProjects\ArcSynthesis\Tut2\Tut2\shaders\";
    shVertex = new VertexShader(new System.IO.FileInfo(shaderPath + "vertex.glsl"));
    shFragment = new FragShader(new System.IO.FileInfo(shaderPath + "fragment.glsl"));
    spMain = new ShaderProgram(shVertex, shFragment);
    spMain.Link();
};

and

game.RenderFrame += (sender, e) =>
{
    GL.ClearColor(0f, 0f, 0f, 0f);
    GL.Clear(ClearBufferMask.ColorBufferBit);

    spMain.Use();

    GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
    GL.EnableVertexAttribArray(0);
    GL.VertexAttribPointer(0, 4, VertexAttribPointerType.Float, false, 0, 0);

    GL.DrawArrays(PrimitiveType.Triangles, 0, 3);

    GL.DisableVertexAttribArray(0);
    GL.UseProgram(0);

    game.SwapBuffers();
};

Vertex shader:

#version 130

in vec4 position;

void main() 
{
    gl_Position = position;
}

Fragment shader:

#version 130

out vec4 outputColor;

void main()
{
    outputColor = vec4(0.2f, 0.5f, 0.8f, 1.0f);
}
1
Did you verify that your shaders successfully load and build? I'm not familiar with these bindings, but in the standard OpenGL API, you could for example use glGetProgramiv(prog, GL_LINK_STATUS, ...) after you link the shader program to verify that it was successful. The shader code itself looks fine, but there could be a problem with the path names.Reto Koradi

1 Answers

1
votes

So I found out that the problem was the line

GL.UseProgram(0);

The shader program class I use (found in some forum) implements the glUseProgram() function like this:

  public IDisposable Use()
  {
     IDisposable r = new ShaderProgram.Handle(curr_program);
     if (curr_program != ID)
     {
        GL.UseProgram(ID);
        curr_program = ID;
     }
     return r;
  }

It only calls glUseProgram() if another ShaderProgram has previously set the static int curr_program to its own ID. It does nothing if the GL shader program has been set to 0 manually by calling GL.UseProgram(0).

I simply removed the line and everything is working now.