# OpenGL: I only see one square instead of a cube / giving information to vertex shader

I am new to OpenGL and tried to follow this tutorial. I use C# and OpenTK. So I translate the C++ Code from the Tutorial:

My C#-Code:

            /* Hintergrundfarbe */
GL.ClearColor(0.0f, 0.0f, 0.4f, 0.0f);

/* Fragments weiter hinten werden automatisch zuerst gerendert */
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Less);

/* Vertex Array Object */
GL.GenVertexArrays(1, out vao);
GL.BindVertexArray(vao);

/* Matrizen */
Projection = Matrix4.Perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
View = Matrix4.LookAt(new Vector3(4, 3, -3), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
//Matrix4 Model = new Matrix4(1.0f);
MVP = View * Projection;

/* Vertices */
var vertices = new Single[]
{
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f
};

/* Farben */
var color = new Single[]
{
0.583f,  0.771f,  0.014f,
0.609f,  0.115f,  0.436f,
0.327f,  0.483f,  0.844f,
0.822f,  0.569f,  0.201f,
0.435f,  0.602f,  0.223f,
0.310f,  0.747f,  0.185f,
0.597f,  0.770f,  0.761f,
0.559f,  0.436f,  0.730f,
0.359f,  0.583f,  0.152f,
0.483f,  0.596f,  0.789f,
0.559f,  0.861f,  0.639f,
0.195f,  0.548f,  0.859f,
0.014f,  0.184f,  0.576f,
0.771f,  0.328f,  0.970f,
0.406f,  0.615f,  0.116f,
0.676f,  0.977f,  0.133f,
0.971f,  0.572f,  0.833f,
0.140f,  0.616f,  0.489f,
0.997f,  0.513f,  0.064f,
0.945f,  0.719f,  0.592f,
0.543f,  0.021f,  0.978f,
0.279f,  0.317f,  0.505f,
0.167f,  0.620f,  0.077f,
0.347f,  0.857f,  0.137f,
0.055f,  0.953f,  0.042f,
0.714f,  0.505f,  0.345f,
0.783f,  0.290f,  0.734f,
0.722f,  0.645f,  0.174f,
0.302f,  0.455f,  0.848f,
0.225f,  0.587f,  0.040f,
0.517f,  0.713f,  0.338f,
0.053f,  0.959f,  0.120f,
0.393f,  0.621f,  0.362f,
0.673f,  0.211f,  0.457f,
0.820f,  0.883f,  0.371f,
0.982f,  0.099f,  0.879f
};

/* Vertex Buffer Object */
GL.GenBuffers(1, out vbo);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(vertices.Length), vertices, BufferUsageHint.StaticDraw);

/* Color Buffer Object */
GL.GenBuffers(1, out cbo);
GL.BindBuffer(BufferTarget.ArrayBuffer, cbo);
GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(vertices.Length), color, BufferUsageHint.StaticDraw);

GL.Viewport(0, 0, Width, Height);
}

protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);

/* Bildschirm loeschen */

GL.UniformMatrix4(MatrixID, false, ref MVP);

/* 1. Attribut */
GL.EnableVertexAttribArray(0);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, IntPtr.Zero);

/* 2. Attribut */
GL.EnableVertexAttribArray(1);
GL.BindBuffer(BufferTarget.ArrayBuffer, cbo);
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, IntPtr.Zero);

/* Zeichnen */
GL.DrawArrays(PrimitiveType.Triangles, 0, 12 * 3);
GL.DisableVertexAttribArray(0);
GL.DisableVertexAttribArray(1);

/* Szene anzeigen */
GL.Flush();
SwapBuffers();
}
}
}


#version 330 core

layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 vertexColor;
out vec3 fragmentColor;
uniform mat4 MVP;

void main()
{
gl_Position =  MVP * vec4(vertexPosition_modelspace,1);
fragmentColor = vertexColor;
}


Fragment:

#version 330 core

in vec3 fragmentColor;
out vec3 color;

void main()
{
color = fragmentColor;
}


The problem: At cameraposition 4, 3, -3 I see nothing:

At cameraposition -3, -3, 0 I see a square:

But the result of the tutorial is this:

Maybe it is because the compiler does not know that three floats of the array are one triangle?

I also do not realy understand how to give information to the vertex shader. Therefore I have seen something like this:

var posAttrib = GL.GetAttribLocation(shaderProgram, "position");
GL.EnableVertexAttribArray(posAttrib);
GL.VertexAttribPointer(posAttrib, 2, VertexAttribPointerType.Float, false, 5 * sizeof(Single), IntPtr.Zero);

GL.EnableVertexAttribArray(colAttrib);
GL.VertexAttribPointer(colAttrib, 3, VertexAttribPointerType.Float, false, 5 * sizeof(Single), new IntPtr(2 * sizeof(Single)));


But in the tutorial they do it like this:

/* 1. Attribut */
GL.EnableVertexAttribArray(0);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, IntPtr.Zero);

/* 2. Attribut */
GL.EnableVertexAttribArray(1);
GL.BindBuffer(BufferTarget.ArrayBuffer, cbo);
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, IntPtr.Zero);


But I don't understand why they use GL.BindBuffer(); again?! Or rather why they do this every frame / update?!.

So why I can't see a cube? What I do wrong?

EDIT: new screenshot:

• Please remove all the code not related to your problem. If you're not sure what code is important to this problem you'll need to do a bit more debugging on your own to narrow the scope of the problem. – MichaelHouse Nov 1 '14 at 14:10
• All right, I improved my question! – user3621741 Nov 1 '14 at 21:24
• I am waiting for this to be reopened so I can add an answer. – Lasse Nov 1 '14 at 21:33
• It seems to be taking ages, so I'll just drop this here: GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(vertices.Length * sizeof(Single)), vertices, BufferUsageHint.StaticDraw); I'll add a better answer when it gets opened. – Lasse Nov 1 '14 at 21:57
• Thank you. It looks better, but it is not a cube. The squares are in a kind of a row. (cameraposition -3, -3, 0) – user3621741 Nov 1 '14 at 22:17

You have this code:

GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(vertices.Length), vertices, BufferUsageHint.StaticDraw);


This tells OpenGL to only upload as many bytes as there are elements in the array. That's why you see only small portion of the data on screen. You need to tell OpenGL how many bytes you actually want to buffer.

GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(vertices.Length * sizeof(Single)), vertices, BufferUsageHint.StaticDraw);


And of course, you need to do that for both buffers.

I like to use OpenTK's Vector3 struct for passing data to the GPU, as it is designed to work well with OpenGL.

var vertices = new Vector3[] { new Vector3(-1,-1,0), new Vector3(0,1,0), new Vector3(1,-1,0) } // 3 vertices to form a single triangle
GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(vertices.Length * Vector3.SizeInBytes), vertices, BufferUsageHint.StaticDraw);


I also do not realy understand how to give information to the vertex shader.I have seen something like this [block of code] But in the tutorial they do it like this [block of code]

The 5th parameter for the GL.VertexAttribPointer defines a stride of the data array you are buffering to the GPU. This is used to determine if there is additional data in the buffer that opengl does not need to worry about, so it can be skipped. You can use this to get the correct stride of the array with OpenTK:

int stride = BlittableValueType.StrideOf(vertices)


But in this case where you only have an array of vertex positions, you don't need stride, and 0 can be passed to the function.

Also the 6th parameter for the GL.VertexAttribPointer defines an offset of where to look for the correct data value. Because the array only holds vertex positions, zero is given because no offsetting is needed. If you combined the two values in a single array, then you would need to add sizeof(Single) * 3 as offset for the color if it is defined in the array after every vertex position.

But I don't understand why they use GL.BindBuffer(); again?! Or rather why they do this every frame / update?!.

When you are not using Vertex Array Objects (VAO), and if you are using multiple buffers for drawing, you need to bind the buffers every frame. This is because OpenGL is a state machine and the buffers currently bound will be used when you issue a draw command. A buffer needs to be bound when you set shader's attribute pointers, or when you are buffering some data in to it.

Of course in this case where you only need to draw the single mesh, you don't need to bind the buffers every frame. But in most OpenGL applications you don't draw a single meshes.

• I change it to this: var vertices = new Vector3[] ..., but GL.BufferData(..., vertices.ToArray(), ...); does not work. Do I have to add a namespace for .ToArray()? – user3621741 Nov 2 '14 at 11:37
• Oops. My bad. Just remove the ToArray() since it's a function of a list to convert it to an array. – Lasse Nov 2 '14 at 11:43
• Yes, I thought so. But again I see no triangle (nothing). I think some Matrix is wrong? (If I remove MVP in the shader I see a triangle) – user3621741 Nov 2 '14 at 12:10
• If you are using the vertices I provided, yes. Those are the usual testing vertices that are used to test if the pipeline is working, and if you apply a projection matrix on the vertices, the triangle will be about one or two pixels in size. I only included them as an example, you should try to convert your data from the tutorial to a vector3 array if you want to use vector3 struct in rendering. – Lasse Nov 2 '14 at 12:15
• You are welcome to join in the chat if you have more questions. This would be easier and more appropriate that way. – Lasse Nov 2 '14 at 12:15