patrickm's picture

[Solved] Black screen troubles

Hello All,

I'm having some trouble with Index Buffer Objects. My code worked fine when I was just using a Vertex Buffer Object and doing ordered draw, but now I'm trying to add an IBO to that, I just get a black screen. My code is below, I would appreciate someone taking a quick glance at it, it's probably something very simple that I've overlooked. Thank you for your time.

Patrick

Main.cs

using System;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Audio;
using OpenTK.Audio.OpenAL;
using OpenTK.Input;
 
namespace opentk30test
{
    class Game : GameWindow
    {
		public mesh m1;
 
		public shader s;
 
		public Matrix4 world;
 
        public Game() : base(800, 600, GraphicsMode.Default, "OpenTK Quick Start Sample")
        {
            VSync = VSyncMode.On;
        }
 
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
 
			Console.WriteLine(GL.GetString(StringName.Version));
 
            GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
            GL.Enable(EnableCap.DepthTest);
			GL.Enable(EnableCap.VertexArray);
			GL.Enable(EnableCap.IndexArray);
 
			s = new shader("vertexShader.glsl", "fragmentShader.glsl");
			Console.WriteLine (s.fragmentShaderMessage);
			Console.WriteLine (s.vertexShaderMessage);
			s.use ();
 
			Vector3[] vertices;
			vertices = new Vector3[3];
			vertices[0].X=0.0f;
			vertices[0].Y=1.0f;
			vertices[0].Z=0.0f;
 
			vertices[1].X=0.0f;
			vertices[1].Y=-1.0f;
			vertices[1].Z=0.0f;
 
			vertices[2].X=-1.0f;
			vertices[2].Y=-1.0f;
			vertices[2].Z=0.0f;
 
 
			uint[] indices = {0,1,2};
 
			m1=new mesh(vertices, indices);
 
 
			world = Matrix4.Scale(0.5f) * Matrix4.CreateRotationZ(0.0f) * Matrix4.CreateTranslation(new Vector3(0.0f, 0.0f, -10.0f));
        }
 
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
 
            GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
 
            Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, Width / (float)Height, 1.0f, 64.0f);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadMatrix(ref projection);
        }
 
        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            base.OnUpdateFrame(e);
 
            if (Keyboard[Key.Escape])
                Exit();
 
			ErrorCode ec = GL.GetError();
			if (ec != 0)
			{
				throw new System.Exception(ec.ToString());
			}
        }
 
        protected override void OnRenderFrame(FrameEventArgs e)
        {
            base.OnRenderFrame(e);
 
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
            Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref modelview);
 
			s.setUniformMatrix4f("gWorld", world);
 
			m1.draw();
 
            SwapBuffers();
        }
 
        [STAThread]
        static void Main()
        {
            using (Game game = new Game())
            {
                game.Run(30.0);
            }
        }
    }
}

Mesh.cs

using System;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
 
namespace opentk30test
{
	public class mesh
	{
		public Vector3[] _vertices;
		public uint[] _indices;
		public uint _vbo;
		public uint _ibo;
 
		public mesh (Vector3[] vertices, uint[] indices)
		{
			_vertices = new Vector3[vertices.Length];
			Array.Copy(vertices, _vertices, vertices.Length);
 
			_indices = new uint[indices.Length];
			Array.Copy(indices, _indices, indices.Length);
 
			GL.GenBuffers(1, out _vbo);
			GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo);
			GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(Vector3.SizeInBytes * _vertices.Length), _vertices, BufferUsageHint.StaticDraw);
 
			GL.GenBuffers(1, out _ibo);
			GL.BindBuffer(BufferTarget.ElementArrayBuffer, _ibo);
			GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(sizeof(uint) * _indices.Length), _indices, BufferUsageHint.StaticDraw);
		}
 
		public void draw()
		{
 
			GL.EnableVertexAttribArray(0);
 
			GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo);
			GL.VertexAttribPointer(0,3,VertexAttribPointerType.Float, false, 0, 0);
 
			GL.BindBuffer(BufferTarget.ElementArrayBuffer, _ibo);
 
			GL.DrawElements(BeginMode.Triangles, _indices.Length, DrawElementsType.UnsignedInt, 0);
 
			GL.DisableVertexAttribArray(0);
		}
	}
}

Shader.cs

using System;
using System.Collections.Generic;
using System.IO;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
 
namespace opentk30test
{
	public class shader
	{
		public int vertexShader;
		public string vertexShaderMessage;
		public int fragmentShader;
		public string fragmentShaderMessage;
		public int program;
 
		public shader(string vertexShaderSource, string fragmentshaderSource)
		{
			vertexShader = GL.CreateShader(ShaderType.VertexShader);
			fragmentShader = GL.CreateShader(ShaderType.FragmentShader);
			program = GL.CreateProgram();
 
			using (StreamReader sr = new StreamReader(vertexShaderSource))
			{
			    GL.ShaderSource(vertexShader, sr.ReadToEnd());
			}
 
			using (StreamReader sr = new StreamReader(fragmentshaderSource))
			{
			    GL.ShaderSource(fragmentShader, sr.ReadToEnd());
			}
 
			GL.CompileShader (vertexShader);
			GL.CompileShader (fragmentShader);
 
			GL.AttachShader (program, vertexShader);
			GL.AttachShader (program, fragmentShader);
 
			GL.LinkProgram (program);
 
			GL.ValidateProgram (program);
 
			vertexShaderMessage = GL.GetShaderInfoLog (vertexShader);
			fragmentShaderMessage = GL.GetShaderInfoLog (fragmentShader);
		}
 
		public void setUniformVar1f(string name, float setVar)
		{
			int temp = GL.GetUniformLocation(program, name);
 
			GL.Uniform1(temp, setVar);
		}
 
		public void setUniformMatrix4f(string name, Matrix4 setVar)
		{
			int temp = GL.GetUniformLocation(program, name);
 
			GL.UniformMatrix4(temp, false, ref setVar);
		}
 
		public void use()
		{
			GL.UseProgram (program);
		}
	}
}

fragmentShader.glsl

#version 330
 
in vec4 Color;
 
out vec4 FragColor;
 
void main()
{
    FragColor = Color;
}

vertexShader.glsl

#version 330
 
layout (location = 0) in vec3 Position;
uniform mat4 gWorld;
 
out vec4 Color;
 
void main()
{
    gl_Position = gWorld * vec4(Position, 1.0);
    Color = vec4(clamp(Position, 0.0, 1.0), 1.0);
}

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Snorkel's picture

- Maybe you're aware of this one already: Shader object's lifetime is incorrect. But this won't cause problems here.

- You don't need the lines "Array.Copy" because an array is actually a reference type.

- on the line with:
GL.VertexAttribPointer(0,3,VertexAttribPointerType.Float, false, 0, 0);
you set the stride to 0, but it should be size of Vector3 in bytes,
GL.VertexAttribPointer(0,3,VertexAttribPointerType.Float, false, 12, 0);

patrickm's picture

Hey, thanks for taking a look. To respond to your points:

1. Not sure what you mean by this, can you clarify? I'm new to this and want to be as correct as possible.

2. I was running into an issue while making 2 meshes with the same array of vertices, I determined that it was because it was passing the array by reference, so the solution was to actually explicitly make a copy of the array.

3. Not sure how this got changed... I changed it to Vector3.SizeInBytes. This does not fix the issue though.

Any other ideas?

Snorkel's picture

1. Actually, I though 's' was a local variable but it looks like it's a member variable, so it's correct.

2. You should be able to use the same array on multiple models unless the vertex data is different.

Your modelview isn't used in the vertex shader.
I'm not sure. But I think you should either use

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

or pass the view and projection matrix as uniforms

gl_Position = projection_matrix * modelview_matrix * vec4(in_position, 1);

other stuff you could try is changing the clear colour to something other than black, maybe you can already see something.
or disable vertex culling.

If you really can't find the solution you could upload your project as a .rar so people on here can just run it and test there changes.

patrickm's picture

I changed the copy statements back to regular assignment, the trouble was that I was using the same array to instantiate 2 meshes, just changing the array, so it caused an issue. Hindsight being 20/20 I should have just used 2 separate arrays.

I'm not using a projection matrix just yet actually. I'm running through this set of tutorials: http://ogldev.atspace.co.uk/index.html and I'm on tutorial 10. This code should just display a triangle whose vertices are the top center of the screen, and the 2 bottom corners.

I've zipped and uploaded my project to my personal server: Link

Snorkel's picture

hey just set the world matrix to identity and you'll see the triangle :)

patrickm's picture

Thank you! I knew it had to be something simple like that. It seems the default far clip plane is 1.0f for some reason. At least, that's what it looks like. If I set the translation piece of my world matrix to 0,0,0 and make one of the Z elements of one of the vertices in my triangle 2.0f, then the triangle gets cut off halfway.

In any case thank you very much for the help, It is much appreciated.

Patrick