Darwin226's picture

Trying to learn not deprecated OpenGL, stuck

I would appreciate a lot if someone could look over my code to see what I did wrong.
It displays a black window with the cursor animation like it's loading. It doesn't get stuck anywhere since the Render function is called every frame. It's supposed to display an image.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Platform.Windows;
using TexLib;
 
namespace _3DRTS {
 
	struct Resources {
 
		public int element_buffer, vertex_buffer;
		public int vertex_shader, fragment_shader, program;
		public int[] textures;
 
		public struct Uniforms {
 
			public int fade_factor;
			public int[] textures;
		}
 
		public Uniforms uniforms;
 
		public struct Attributes {
 
			public int position;
		}
 
		public Attributes attributes;
 
		public float fade_factor;
	}
 
	class World : GameWindow {
 
		float[] g_vertex_buffer_data = { 
				-1.0f, -1.0f,
				1.0f, -1.0f,
				-1.0f,  1.0f,
				1.0f,  1.0f
			};
		uint[] g_element_buffer_data = { 0, 1, 2, 3 };
 
		Resources g_resources;
 
		int miliseconds = 0;
 
		public World ()
			: base( 700, 440 ) {
 
			Run();
		}
 
		protected override void OnLoad ( EventArgs e ) {
 
			base.OnLoad( e );
 
			MakeResources();
 
			Stopwatch timer = new Stopwatch();
			while ( true ) {
 
				timer.Start();
				Update();
				Render();
 
				Title = timer.ElapsedMilliseconds + "";
				System.Threading.Thread.Sleep( timer.ElapsedMilliseconds <= 16 ? 16 - (int)timer.ElapsedMilliseconds : 0 );
				timer.Reset();
			}
		}
 
		void Update () {
 
			miliseconds += 60;
			g_resources.fade_factor = (float)Math.Sin( miliseconds * 0.001f ) * 0.5f + 0.5f;
			Console.WriteLine( g_resources.fade_factor );
		}
 
		void Render () {
 
			GL.Clear( ClearBufferMask.ColorBufferBit );
 
			GL.UseProgram( g_resources.program );
			GL.Uniform1( g_resources.uniforms.fade_factor, g_resources.fade_factor );
 
			GL.ActiveTexture( TextureUnit.Texture0 );
			GL.BindTexture( TextureTarget.Texture2D, g_resources.textures[ 0 ] );
			GL.Uniform1( g_resources.uniforms.textures[ 0 ], 0 );
 
			GL.ActiveTexture( TextureUnit.Texture0 );
			GL.BindTexture( TextureTarget.Texture2D, g_resources.textures[ 1 ] );
			GL.Uniform1( g_resources.uniforms.textures[ 1 ], 1 );
 
			GL.BindBuffer( BufferTarget.ArrayBuffer, g_resources.vertex_buffer );
			GL.VertexAttribPointer( g_resources.attributes.position, 2, VertexAttribPointerType.Float, false, sizeof( float ) * 2, 0 );
			GL.EnableVertexAttribArray( g_resources.attributes.position );
 
			GL.BindBuffer( BufferTarget.ElementArrayBuffer, g_resources.element_buffer );
 
			GL.DrawElements( BeginMode.TriangleStrip, 4, DrawElementsType.UnsignedInt, 0 );
 
			GL.DisableVertexAttribArray( g_resources.attributes.position );
 
			SwapBuffers();
		}
 
		int MakeShader ( ShaderType type, string filename ) {
 
			string source;
 
			using ( System.IO.StringReader stream = new System.IO.StringReader( filename ) ) {
 
				source = stream.ReadToEnd();
			}
			int shader;
			int shader_ok;
 
			shader = GL.CreateShader( type );
			GL.ShaderSource( shader, source );
			GL.CompileShader( shader );
			GL.GetShader( shader, ShaderParameter.CompileStatus, out shader_ok );
 
			if ( shader_ok != 0 ) {
				Console.WriteLine( "Failed to compile {0}:\n", filename );
				int logLength;
				StringBuilder log = new StringBuilder();
				int temp;
 
				GL.GetShader( shader, ShaderParameter.InfoLogLength, out logLength );
				GL.GetShaderInfoLog( shader, logLength, out temp, log );
				Console.WriteLine( log.ToString() );
 
				GL.DeleteShader( shader );
				return 0;
			}
 
			return shader;
		}
 
		int MakeProgram ( int vertex_shader, int fragment_shader ) {
 
			int program_ok;
 
			int program = GL.CreateProgram();
			GL.AttachShader( program, vertex_shader );
			GL.AttachShader( program, fragment_shader );
			GL.LinkProgram( program );
 
			GL.GetProgram( program, ProgramParameter.LinkStatus, out program_ok );
			if ( program_ok != 0 ) {
 
				Console.WriteLine( "Failed to link shader program:\n" );
				int logLength;
				StringBuilder log = new StringBuilder();
				int temp;
 
				GL.GetProgram( program, ProgramParameter.InfoLogLength, out logLength );
				GL.GetProgramInfoLog( program, logLength, out temp, log );
				Console.WriteLine( log.ToString() );
 
				GL.DeleteProgram( program );
				return 0;
			}
			return program;
		}
 
		int MakeResources () {
 
			g_resources.uniforms.textures = new int[ 2 ];
			g_resources.textures = new int[ 2 ];
 
			g_resources.vertex_buffer = MakeBuffer( BufferTarget.ArrayBuffer, g_vertex_buffer_data, new IntPtr( sizeof( float ) * g_vertex_buffer_data.Length ) );
			g_resources.element_buffer = MakeBuffer( BufferTarget.ElementArrayBuffer, g_element_buffer_data, new IntPtr( sizeof( uint ) * g_element_buffer_data.Length ) );
 
			g_resources.textures[ 0 ] = TexUtil.CreateTextureFromFile( "hello1.png" );
			g_resources.textures[ 1 ] = TexUtil.CreateTextureFromFile( "hello2.png" );
 
			if ( g_resources.textures[ 0 ] == 0 || g_resources.textures[ 1 ] == 0 )
				return 0;
 
			/* make buffers and textures ... */
			g_resources.vertex_shader = MakeShader( ShaderType.VertexShader, "hello-gl.v.glsl" );
			if ( g_resources.vertex_shader == 0 ) return 0;
 
			g_resources.fragment_shader = MakeShader( ShaderType.FragmentShader, "hello-gl.f.glsl" );
			if ( g_resources.fragment_shader == 0 ) return 0;
 
			g_resources.program = MakeProgram( g_resources.vertex_shader, g_resources.fragment_shader );
			if ( g_resources.program == 0 ) return 0;
 
			g_resources.uniforms.fade_factor = GL.GetUniformLocation( g_resources.program, "fade_factor" );
			g_resources.uniforms.textures[ 0 ] = GL.GetUniformLocation( g_resources.program, "textures[0]" );
			g_resources.uniforms.textures[ 1 ] = GL.GetUniformLocation( g_resources.program, "textures[1]" );
 
			g_resources.attributes.position = GL.GetAttribLocation( g_resources.program, "position" );
 
			return 1;
		}
 
		int MakeBuffer<T2> ( BufferTarget target, T2[] buffer_data, IntPtr buffer_size ) where T2 : struct {
 
			int buffer;
			GL.GenBuffers( 1, out buffer );
			GL.BindBuffer( target, buffer );
			GL.BufferData( target, buffer_size, buffer_data, BufferUsageHint.StaticDraw );
 
			return buffer;
		}
	}
}

I've also uploaded the whole project here if you need to compile it yourself or something.
This is the tutorial I'm trying to follow, unfortunately it's in C so I had some troubles.

Big thanks to anyone that tries to help.


Comments

Comment viewing options

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

Unlike DirectX you need to set stride parameter of VertexAttribPointer to "0"(zero)

documentation

Darwin226's picture

Ok, I changed the sizeof(float)*2 to 0, still the same result.

I'm sure people use this stuff on a daily basis, surely someone would know what I did wrong.

zahirtezcan's picture

Ok, I have downloaded your source and tried to debug it here are the main probs:
- You need to give contents of the shader file to GL.ShaderSource (this method does not accept file name)
- You need to check whether compile/link status is zero (zero = failure)

edit: I suggest overriding OnRenderFrame / OnUpdateFrame methods instead of maing your own
edit2: I forgot to mention that your window is getting disposed, you need to change the line in your Program.cs as follows:

using (var world = new World())
{
	world.Run();
}
Darwin226's picture

Ok, thanks for taking the time to help.

I figured out the problem when I tried tracing the source, apparently I was using StringReader instead of StreamReader :P

I never figured out what but something is very wrong with Update and Render times in OpenTK. VSync sometimes just plain doesn't work, sometimes is makes the whole thing lag and whatnot. Decided that the easiest way is to make my own gameloop.

Didn't know about that last one, thanks.

Darwin226's picture

Btw, sometimes when I run it, it runs fine for a few seconds. Then it stops working and crashes. What's up with that?