Search code examples
c#winformsopenglglslopentk

C# OpenTK GLControl drawing cube incorrect


I use OpenTK's GLControl in C# WinForm (.NET Framework) Application, but I don't know why my 20mm3 cube scaled alone with my form.

I inherit GLControl with DCGLControl and add GL.Viewport(ClientRectangle) when control resize :

private void DCGLControl_Resize(object sender, EventArgs e)
{
    GL.Viewport(ClientRectangle);
    Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, Width / (float)Height, 1.0f, 1000f);
    GL.MatrixMode(MatrixMode.Projection);
    GL.LoadMatrix(ref projection);
}

And here is my DCGLControl_Load event (initialize something and start a new thread to render it):

private void DCGLControl_Load(object sender, EventArgs e)
{
    GL.Enable(EnableCap.DepthTest);
    GL.ClearColor(ClearColor);
    Resize += DCGLControl_Resize;

    Matrix4 trans;
    trans = Matrix4.CreateScale(0.01f, 0.01f, 0.01f);

    Context.MakeCurrent(null);
    renderThread = new Thread(() =>
    {
        Context.MakeCurrent(WindowInfo);
        while (true)
        {
            int n;
            for (n = 0; n < Models.Count; n++)
                if (Models[n].VAO == 0)
                {
                    Models[n].Shader.Compile();
                    GenVAO(Models[n]);
                }
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            GL.Viewport(ClientRectangle);


            for (n = 0; n < Models.Count; n++)
            {
                GL.BindVertexArray(Models[n].VAO);

                Models[n].Shader.Use();
                Models[n].Shader.SetMatrix4("transform", trans);

                if (Models[n].UseEBO)
                    GL.DrawElements(Models[n].PrimitiveType, Models[n].DrawOrder.Length, DrawElementsType.UnsignedInt, 0);
                else
                    GL.DrawArrays(Models[n].PrimitiveType, 0, Models[n].Vertices.Length);
            }
            SwapBuffers();
            Thread.Sleep(1000/60);
        }
    });

    renderThread.Start();
}

And here is my vertex shader :

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;

uniform mat4 transform;

void main()
{
    gl_Position =  transform * vec4(position, 1.0);
}

I got result like this : error screenshot

I am a beginner with OpenGL and OpenTK, thanks for help me :)


Solution

  • You cannot mix the fixed function matrices with the matrix transformations in 3.30 core shader. This means that the instruction GL.MatrixMode(MatrixMode.Projection); has no effect (except an OpenGL error in a core profile context). You have to add a projection matrix to the shader:

    #version 330 core
    layout (location = 0) in vec3 position;
    layout (location = 1) in vec3 normal;
    
    uniform mat4 projection;
    uniform mat4 transform;
    
    void main()
    {
        gl_Position = projection * transform * vec4(position, 1.0);
    }
    

    Add an attribute for the projection matrix:

    private Matrix4 projection;
    

    Set the matrix in the DCGLControl_Resize callback:

    private void DCGLControl_Resize(object sender, EventArgs e)
    {
        GL.Viewport(ClientRectangle);
        self.projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, Width / (float)Height, 1.0f, 1000f);
    }
    

    Set the matrix uniform before drawing the geoemtry:

    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
    GL.Viewport(ClientRectangle);
    
    for (n = 0; n < Models.Count; n++)
    {
        GL.BindVertexArray(Models[n].VAO);
    
        Models[n].Shader.Use();
        Models[n].Shader.SetMatrix4("projection", self.projection);
        Models[n].Shader.SetMatrix4("transform", trans);
    
        if (Models[n].UseEBO)
            GL.DrawElements(Models[n].PrimitiveType, Models[n].DrawOrder.Length, DrawElementsType.UnsignedInt, 0);
        else
            GL.DrawArrays(Models[n].PrimitiveType, 0, Models[n].Vertices.Length);
    }
    SwapBuffers();