7

I'm currently trying to get into GLSL using the OpenGL superbible and http://www.learnopengl.com/. My desired environment is OpenTK.

I tried to convert the "Hello Triangle" entry level tutorial from learnopengl.com into OpenTK, it is meant to draw a triangle using very simple shaders, without using any perspective/world/model transformations.

My result is just the colorbuffer, but else an empty window and i simply do not understand where i have made a mistake so any help in finding and more importantly understanding them would be very appreciated.

My OpenTK code:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;

namespace learnopengl.HelloTriangle
{
    public class MainWindow : GameWindow
    {
        int _shaderId;
        int _vao;
        int _glbuf;
        int _fragObj;
        int _vertexObj;
        Vector3[] _triangleVert;

        public MainWindow()
            : base(800,600)
        {
            KeyDown += MainWindow_KeyDown;
            _triangleVert = new Vector3[] { 
                new Vector3(-0.5f, -0.5f, 0.0f),
                new Vector3(0.5f, -0.5f, 0.0f),
                new Vector3(-0.5f, 0.5f, 0.0f)
            };

        }

        void MainWindow_KeyDown(object sender, KeyboardKeyEventArgs e)
        {
            if (e.Key == Key.Escape)
                this.Exit();

            if (e.Key == Key.F11)
                if (this.WindowState == WindowState.Fullscreen)
                    this.WindowState = WindowState.Normal;
                else
                    this.WindowState = WindowState.Fullscreen;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            System.Diagnostics.Trace.WriteLine(string.Format("OpenGL version: {0}", GL.GetString(StringName.Version)));
            GL.ClearColor(Color.Purple);

            _vertexObj = GL.CreateShader(ShaderType.VertexShader);
            _fragObj = GL.CreateShader(ShaderType.FragmentShader);
            int statusCode;
            string info;

            GL.ShaderSource(_vertexObj, File.ReadAllText(@"shader\triangle.vert"));
            GL.CompileShader(_vertexObj);
            info = GL.GetShaderInfoLog(_vertexObj);
            Console.Write(string.Format("triangle.vert compile: {0}",info));
            GL.GetShader(_vertexObj, ShaderParameter.CompileStatus, out statusCode);
            if (statusCode != 1) throw new ApplicationException(info);

            GL.ShaderSource(_fragObj, File.ReadAllText(@"shader\triangle.frag"));
            GL.CompileShader(_fragObj);
            info = GL.GetShaderInfoLog(_fragObj);
            Console.Write(string.Format("triangle.frag compile: {0}", info));
            GL.GetShader(_fragObj, ShaderParameter.CompileStatus, out statusCode);
            if (statusCode != 1) throw new ApplicationException(info);

            _shaderId = GL.CreateProgram();
            GL.AttachShader(_shaderId, _fragObj);
            GL.AttachShader(_shaderId, _vertexObj);
            GL.LinkProgram(_shaderId);
            Console.Write(string.Format("link program: {0}", GL.GetProgramInfoLog(_shaderId)));
            GL.UseProgram(_shaderId);
            Console.Write(string.Format("use program: {0}", GL.GetProgramInfoLog(_shaderId)));

            _vao = GL.GenVertexArray();
            _glbuf = GL.GenBuffer();
            GL.BindVertexArray(_vao);
            GL.BindBuffer(BufferTarget.ArrayBuffer, _glbuf);
            GL.BufferData<Vector3>(BufferTarget.ArrayBuffer, new IntPtr(Vector3.SizeInBytes * _triangleVert.Length), _triangleVert, BufferUsageHint.StaticDraw);
            GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes * _triangleVert.Length, 0);
            GL.EnableVertexAttribArray(0);
            GL.BindVertexArray(0);
        }

        protected override void OnResize(EventArgs e)
        {
            GL.Viewport(0, 0, Width, Height);
        }

        protected override void OnRenderFrame(FrameEventArgs e)
        {
            GL.Clear(ClearBufferMask.ColorBufferBit);

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

            this.SwapBuffers();
        }

        protected override void OnUnload(EventArgs e)
        {
            GL.DeleteProgram(_shaderId);
            GL.DeleteShader(_vertexObj);
            GL.DeleteShader(_fragObj);
            GL.DeleteVertexArray(_vao);
            GL.DeleteBuffer(_glbuf);
            base.OnClosed(e);
        }
    }
}

triangle.vert:

#version 330 core

layout(location = 0) in vec3 position;

void main()
{
    gl_Position = vec4(position.x, position.y, position.z, 1.0f);
}

triangle.frag:

#version 330 core

//out vec4 color;

void main()
{
    gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
    //color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}

My Result: enter image description here

Edit: Updated the code with the suggestions from the comments, which don't change the outcome.

Also verified that the vbo is filled correctly with gDEBugger: enter image description here

Edit2: I added the Info log from linking/using the shaders and reroutet all info log to the console. I get some warnings which can be ignored.

enter image description here

I also tested if any changes occur if i remove the float suffix from all shaders, but everything stayed the same.

Sors
  • 494
  • 1
  • 4
  • 12
  • 1
    1-Download the OpenTK debug DLL and execute your program, if there's any problem it will write it to the Output window. 2-Try changing your fragment to this: gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f); – Gusman Jan 06 '16 at 21:22
  • @Gusman Thanks for the info about the debug version of OpenTK, but there are no errors reported with my old fragment shader and everything is the same with your change to it. – Sors Jan 06 '16 at 22:12
  • 1
    The last argument to `GL.VertexAttribPointer` defines the byte offset of the vertex attribute in the data stored in the currently bound VBO. Here you pass in the vertex array data which is most likely not your intention. In your case it should simply be `0`. – Joey Dewd Jan 07 '16 at 10:26
  • @Joe i changed the code, but the result is still the same – Sors Jan 07 '16 at 10:56
  • Strange, perhaps it's smart to also check for linker errors when you compile the shader program. The shader linker can also generate errors that can tell you interesting stuff. For instance, if you get a shader linker error stating something like 'must write to gl_Position' it's likely that your shaders haven't been loaded correctly. – Joey Dewd Jan 07 '16 at 13:21
  • @joe already checked for it with no result, but i will add it to the code again – Sors Jan 07 '16 at 14:00

1 Answers1

5

Finally found an answer to the problem it's the line:

GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes * _triangleVert.Length, 0);

The 5th parameter is meant to only specify a single attribute's size, not of the whole array:

GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);

Now it works like it should, thanks for all the helpful comments!

Sors
  • 494
  • 1
  • 4
  • 12
  • You should mark this as the answer; it's extremely helpful to people like me..barely almost don't nearly not know what they're doing. – CJ Burkey Dec 27 '17 at 00:20