Search code examples
graphicsf#opentk

OpenTK black triangle?


Before refering to it, I have read OpenTK - fragment shader is not working (triangle is always black) and it did not help.

I'm trying to do the 'hello triangle' tutorial, for OpenTK in F#. But my triangle is black instead of orange. I guess that it is somehow the fragment shader that is not working correctly but can't find out why. https://opentk.net/learn/chapter1/2-hello-triangle.html

Shader class

type Shader(vertexpath, fragmentpath) as shader =
    let mutable handle = GL.CreateProgram()
    let mutable disposed = false
    let mutable vertexShader = GL.CreateShader(ShaderType.VertexShader)
    let mutable fragmentShader = GL.CreateShader(ShaderType.FragmentShader)
    
    do
        // vertexshader
        let mutable shaderSource = load vertexpath
        let mutable vertexShader = GL.CreateShader ShaderType.VertexShader
        GL.ShaderSource(vertexShader, shaderSource)
        shader.CompileShader(vertexShader)

        // fragmentshader
        let mutable shaderSource = load fragmentpath
        let mutable fragmentShader = GL.CreateShader ShaderType.VertexShader
        GL.ShaderSource(vertexShader, shaderSource)
        shader.CompileShader(fragmentShader)



        GL.AttachShader(handle, vertexShader)
        GL.AttachShader(handle, fragmentShader)

        shader.LinkProgram(handle)

        GL.DetachShader(handle, vertexShader)
        GL.DetachShader(handle, fragmentShader)
        GL.DeleteShader(fragmentShader)
        GL.DeleteShader(vertexShader)  


member _.Dispose() = 
    if not disposed then
        GL.DetachShader(handle, vertexShader)
        GL.DetachShader(handle, fragmentShader)
        GL.DeleteShader(vertexShader)
        GL.DeleteShader(fragmentShader)
        GL.DeleteProgram(handle)
        disposed <- true

member _.Use() = GL.UseProgram(handle) 

member _.CompileShader shader = 
    let mutable code = 0
    GL.CompileShader shader
    let info = GL.GetShaderInfoLog(shader)
    if System.String.IsNullOrEmpty info then
        printfn $"{info}"


    GL.GetShader(shader, ShaderParameter.CompileStatus, &code)
    if code <> int All.True then
        let infoLog = GL.GetShaderInfoLog shader
        failwith $"Error occured whilst compiling Shader({shader}).\n\n{infoLog}"


member _.LinkProgram (program: int) =
    let mutable code = 0

    GL.LinkProgram program
    let info = GL.GetProgramInfoLog(program)
    if System.String.IsNullOrEmpty info then
        printfn $"{info}"

    GL.GetProgram(program, GetProgramParameterName.LinkStatus, &code)
    if code <> int All.True then
        failwith $"Error occurred whilst linking Program({program})"
     

where

let load (path: string) = 
    (new StreamReader(path, Encoding.UTF8)).ReadToEnd() 
    |> fun str -> 
        printfn $"{str}"
        str

Window Class

type Window(width, height, ?title) as Win =
    inherit 
        // diviation from code on github
        GameWindow(
            GameWindowSettings.Default,
            new NativeWindowSettings()
        )

    let mutable title = defaultArg title ""


    let vertices =
        [|
            -0.5f; -0.5f; 0.0f;
             0.5f; -0.5f; 0.0f;
             0.0f;  0.5f; 0.0f;
        |]

    // throw execption if not initiated 
    let mutable vertexBufferObject = -1
    let mutable vertexArrayObject  = -1

    let mutable shader = new Shader("Shaders\shader.vert", "Shaders\shader.frag") 
    

    do
        Win.Size <- (width, height)
        Win.Title <- title
override _.OnLoad() =

        base.OnLoad()
        
        GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f)

        
        vertexBufferObject <- GL.GenBuffer()

        GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBufferObject)
        GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * 4, vertices, BufferUsageHint.StaticDraw)

        vertexArrayObject <- GL.GenVertexArray()
        GL.BindVertexArray(vertexArrayObject)

        // shader not yet implemented?? 
        GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 3 * 4, 0)

        GL.EnableVertexAttribArray(0)

      
        shader.Use()
       




    override _.OnUnload() =

        GL.BindBuffer(BufferTarget.ArrayBuffer, 0)
        GL.BindVertexArray(0)
        GL.UseProgram(0)

        GL.DeleteBuffer(vertexBufferObject)
        GL.DeleteVertexArray(vertexArrayObject)
        shader.Dispose()
        base.OnUnload()

  


    override _.OnRenderFrame e =
        base.OnRenderFrame e

        GL.Clear(ClearBufferMask.ColorBufferBit)

        shader.Use() 

        GL.BindVertexArray(vertexArrayObject)
        
        GL.DrawArrays(PrimitiveType.Triangles, 0, 3)

        Win.SwapBuffers()
        

    override _.OnResize e = 
        base.OnResize e
        GL.Viewport(0, 0, fst Win.Size, snd Win.Size)


    override _.OnUpdateFrame e =

        base.OnUpdateFrame e

        if Win.KeyboardState.IsKeyDown(Keys.Escape) then
            Win.Close()

the indentation is off, I know. Again the program runs without error except for the triangle not being the proper colour. Is have used https://github.com/opentk/LearnOpenTK/blob/master/Chapter1/2-HelloTriangle/Window.cs

and

https://github.com/opentk/LearnOpenTK/blob/master/Common/Shader.cs to troubleshoot my code

The shader.vert and shader.frag are copy pasted from the git repo above.


Solution

  • I found the error, I was targeting the vertexshader object when compiling both shaders