c# – VAO VBO drawing geometry

Question:

I recently started working with opengle. At the moment I am trying to implement the simplest "butcher". In the given code – the minimum sequence of actions for drawing geometry. Stuck at the stage of filling VBO and VAO with correct data.

A textured, colored quad is NOT drawn on my screen.

The given code is not just taken from the head, but written based on several examples. There were no problems as long as Vertex2D consisted of only 1 attribute (x, y). Then I added texture coordinates and color. This is where my head started spinning.

Tell me about the correct way to achieve this in my example.

1) glVertexAttribPointer or glVertexPointer? and at what point? (VAO state ..?)

2) What glEnable … () functions should I use? and at what point? (VAO state ..?)

If I am doing something completely wrong or the essence of the issue is not clear, please let me know!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using OpenTK.Graphics.OpenGL;

namespace test
{
    public struct Vertex
    {
        float X, Y;
        float U, V;
        float R, G, B, A;

        public Vertex(float x, float y, float u, float v, float r, float g, float b, float a)
        {
            X = x; Y = y;
            U = u; V = v;
            R = r; G = g; B = b; A = a;
        }
        public const int Stride = 32;
    }

    class VboRenderer
    {
        private int VaoId;
        private int VboId;

        private Vertex[] Vertices;

        public VboRenderer()
        {
            InitializeVBO();
        }

        private void InitializeVBO()
        {
            //Simple quad from 2 tris in CW
            Vertices = new Vertex[6]
            {
                new Vertex(0, 0, 0, 0, 255, 255, 255, 255),
                new Vertex(1, 0, 1, 0, 255, 255, 255, 255),
                new Vertex(0, 1, 0, 1, 255, 255, 255, 255),

                new Vertex(0, 1, 0, 1, 255, 255, 255, 255),
                new Vertex(1, 0, 1, 0, 255, 255, 255, 255),
                new Vertex(1, 1, 1, 1, 255, 255, 255, 255),
            };

            //Ids
            GL.GenVertexArrays(1, out VaoId);
            GL.GenBuffers(1, out VboId);

            //Generate a vao array
            GL.BindVertexArray(VaoId);
            GL.BindBuffer(BufferTarget.ArrayBuffer, VboId);
            GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, Vertex.Stride, (IntPtr)(sizeof(float) * 0));
            GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex.Stride, (IntPtr)(sizeof(float) * 2));
            GL.VertexAttribPointer(2, 4, VertexAttribPointerType.Float, false, Vertex.Stride, (IntPtr)(sizeof(float) * 4));
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
            GL.EnableVertexAttribArray(0);
            GL.EnableVertexAttribArray(1);
            GL.EnableVertexAttribArray(2);
            GL.BindVertexArray(0);

            //Generate a vbo buffer
            GL.BindBuffer(BufferTarget.ArrayBuffer, VboId);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(Vertices.Length * Vertex.Stride),
                Vertices, BufferUsageHint.StaticDraw);
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
        }

        public void RenderVBO(float x, float y, float size, float rot)
        {
            GL.PushMatrix();

            //Model-view
            Matrix4 transform = Matrix4.Identity;
            transform = Matrix4.Mult(transform, Matrix4.CreateScale((float)size, (float)size, 1.0f));
            transform = Matrix4.Mult(transform, Matrix4.CreateRotationZ((float)rot));
            transform = Matrix4.Mult(transform, Matrix4.CreateTranslation(x, y, 0.0f));
            GL.MultMatrix(ref transform);

            //Bindings
            GL.BindTexture(TextureTarget.Texture2D, Main.texture.Handle);
            GL.BindVertexArray(VaoId);

            //Render
            GL.DrawArrays(PrimitiveType.Triangles, 0, 1);

            //Un bindings
            GL.BindTexture(TextureTarget.Texture2D, 0);
            GL.BindVertexArray(0);

            GL.PopMatrix();
        }
    }
}

Answer:

opentk didn't use it, but I don't think they shied away from the opengl API when implementing binding. So I will give the answer based on knowledge of the openGL API if you don't mind.

First, this is

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

change to

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

since you draw a square with 2 triangles, which each has 3 vertices, in total 6 vertices come out, and for some reason you only indicated 1 vertex.

Secondly, here is this part of the code:

    //Ids
    GL.GenVertexArrays(1, out VaoId);
    GL.GenBuffers(1, out VboId);

    //Generate a vao array
    GL.BindVertexArray(VaoId);
    GL.BindBuffer(BufferTarget.ArrayBuffer, VboId);
    GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, Vertex.Stride, (IntPtr)(sizeof(float) * 0));
    GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex.Stride, (IntPtr)(sizeof(float) * 2));
    GL.VertexAttribPointer(2, 4, VertexAttribPointerType.Float, false, Vertex.Stride, (IntPtr)(sizeof(float) * 4));
    GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
    GL.EnableVertexAttribArray(0);
    GL.EnableVertexAttribArray(1);
    GL.EnableVertexAttribArray(2);
    GL.BindVertexArray(0);

    //Generate a vbo buffer
    GL.BindBuffer(BufferTarget.ArrayBuffer, VboId);
    GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(Vertices.Length * Vertex.Stride),
        Vertices, BufferUsageHint.StaticDraw);
    GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

fill in vbo after call

GL.BindBuffer(BufferTarget.ArrayBuffer, VboId);

and there is absolutely no need to do it later with an unbinding string

GL.BindBuffer(BufferTarget.ArrayBuffer, 0); since to activate or reset the entire rendering state, the binding and unbinding the vao itself is vao

in general, here is the corrected part of this code:

    // Ids
    GL.GenVertexArrays(1, out VaoId);
    GL.GenBuffers(1, out VboId);
    // Generate a vao array
    GL.BindVertexArray(VaoId);

       // Generate a vbo buffer
       GL.BindBuffer(BufferTarget.ArrayBuffer, VboId);
       GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(Vertices.Length * Vertex.Stride),
        Vertices, BufferUsageHint.StaticDraw);           

       GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, Vertex.Stride, (IntPtr)(sizeof(float) * 0));
       GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex.Stride, (IntPtr)(sizeof(float) * 2));
       GL.VertexAttribPointer(2, 4, VertexAttribPointerType.Float, false, Vertex.Stride, (IntPtr)(sizeof(float) * 4));  

       GL.EnableVertexAttribArray(0);
       GL.EnableVertexAttribArray(1);
       GL.EnableVertexAttribArray(2);         

    GL.BindVertexArray(0);

And the texture must also be passed to the fragment shader through uniform after the line

GL.BindTexture(TextureTarget.Texture2D, Main.texture.Handle);

still need to write

glUniform1i(glGetUniformLocation("texture"), 0)

where texture defined in the fragment shader as

uniform sampler2D texture;
void main() { gl_FragColor = texture2D(texture, texCoord); }

good luck

Scroll to Top