Goepfie's picture

Vector2h - VBO - Texcoord - Crash - Possible Bug?

Hey,
I am getting to know OpenTK and did put together some examples and things I read about VBOs. Everything is working fine until I started using Vector2h in my ArrayBuffers.

This is the working code:

// Released to the public domain. Use, modify and relicense at will.
 
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
 
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
 
namespace StarterKit
{	
    class Game : GameWindow
    {
		Vector2[] coord;
		Vector2[] tex;
		uint[] VBOids = new uint[2];
 
        /// <summary>Creates a 800x600 window with the specified title.</summary>
        public Game()
            : base(640, 480, GraphicsMode.Default, "Testbed")
        {
            VSync = VSyncMode.On;
        }
 
 
        /// <summary>Load resources here.</summary>
        /// <param name="e">Not used.</param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
 
			GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
			coord = new Vector2[4];
			tex = new Vector2[4];
 
			coord[0] = new Vector2(-512, 386);
			tex[0] = new Vector2(0, 1f/1024);
 
			coord[1] = new Vector2(512, 386);
			tex[1] = new Vector2(1f, 1f/1024f);
 
			coord[2] = new Vector2(512, -386);
			tex[2] = new Vector2(1f, 769f/1024f);
 
			coord[3] = new Vector2(-512, -386);
			tex[3] = new Vector2(0, 769f/1024f);
 
			int bufferSize = 0;
 
			// Generate Array Buffer Id
 
 
			// Texture Array Buffer
			{ 
				GL.GenBuffers (1, out VBOids[0]);
 
				// Bind current context to Array Buffer ID
				GL.BindBuffer (BufferTarget.ArrayBuffer, VBOids[0]);
 
				// Send data to buffer
				GL.BufferData (BufferTarget.ArrayBuffer, (IntPtr)(tex.Length * Vector2.SizeInBytes), tex, BufferUsageHint.DynamicDraw);
 
				// Validate that the buffer is the correct size
				GL.GetBufferParameter (BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out bufferSize);
				if (tex.Length * Vector2.SizeInBytes != bufferSize)
					throw new ApplicationException ("Vertex array not uploaded correctly");
 
				// Clear the buffer Binding
				GL.BindBuffer (BufferTarget.ArrayBuffer, 0);
			}
 
			// Vertex Array Buffer
			{ 
				GL.GenBuffers (1, out VBOids[1]);
 
				// Bind current context to Array Buffer ID
				GL.BindBuffer (BufferTarget.ArrayBuffer, VBOids[1]);
 
				// Send data to buffer
				GL.BufferData (BufferTarget.ArrayBuffer, (IntPtr)(coord.Length * Vector2.SizeInBytes), coord, BufferUsageHint.DynamicDraw);
 				if ( ! GL.IsBuffer( VBOids[0] ))
					throw new ApplicationException ("Vertex array not uploaded correctly");
 
				// Validate that the buffer is the correct size
				GL.GetBufferParameter (BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out bufferSize);
				if (coord.Length * Vector2.SizeInBytes != bufferSize)
					throw new ApplicationException ("Vertex array not uploaded correctly");
 
				// Clear the buffer Binding
				GL.BindBuffer (BufferTarget.ArrayBuffer, 0);
			}
 
 
			GL.Enable(EnableCap.Texture2D);
			GL.BindTexture( TextureTarget.Texture2D, LoadTexture("keymap_0.png"));
        }
 
        /// <summary>
        /// Called when your window is resized. Set your viewport here. It is also
        /// a good place to set up your projection matrix (which probably changes
        /// along when the aspect ratio of your window).
        /// </summary>
        /// <param name="e">Not used.</param>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
 
            GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
        }
 
        /// <summary>
        /// Called when it is time to setup the next frame. Add you game logic here.
        /// </summary>
        /// <param name="e">Contains timing information for framerate independent logic.</param>
        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            base.OnUpdateFrame(e);
 
            if (Keyboard[Key.Escape])
                Exit();
        }
 
        /// <summary>
        /// Called when it is time to render the next frame. Add your rendering code here.
        /// </summary>
        /// <param name="e">Contains timing information.</param>
        protected override void OnRenderFrame(FrameEventArgs e)
        {
            base.OnRenderFrame(e);
 
			GL.Disable(EnableCap.DepthTest);
 
        	GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
	        Matrix4 modelview = Matrix4.LookAt(Vector3.UnitZ, Vector3.Zero, Vector3.UnitY);
	        GL.MatrixMode(MatrixMode.Modelview);
	        GL.LoadMatrix(ref modelview);
 
	        GL.MatrixMode(MatrixMode.Projection);
	        GL.LoadIdentity();
 
			GL.Ortho(-512, 512, -386, 386, -1, 1);
 
			// Vertex Array Buffer
			{
				// Bind to the Array Buffer ID
				GL.BindBuffer (BufferTarget.ArrayBuffer, VBOids[0]);
 
				// Set the Pointer to the current bound array describing how the data ia stored
				GL.TexCoordPointer (2, TexCoordPointerType.Float, 0, 0);
 
				// Enable the client state so it will use this array buffer pointer
				GL.EnableClientState (ArrayCap.TextureCoordArray);
			}
 
			// Vertex Array Buffer
			{
				// Bind to the Array Buffer ID
				GL.BindBuffer (BufferTarget.ArrayBuffer, VBOids[1]);
 
				// Set the Pointer to the current bound array describing how the data ia stored
				GL.VertexPointer (2, VertexPointerType.Float, 0 , 0 );
 
				// Enable the client state so it will use this array buffer pointer
				GL.EnableClientState (ArrayCap.VertexArray);
			}
 
			// Element Array Buffer
			{ 
				// Draw the elements in the element array buffer
				// Draws up items in the Color, Vertex, TexCoordinate, and Normal Buffers using indices in the ElementArrayBuffer
				GL.DrawArrays(BeginMode.Quads, 0, 4);
			}
 
 
			/*
			GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.TextureCoordArray);
 
		        GL.VertexPointer(2, VertexPointerType.Float, BlittableValueType.StrideOf(coord), coord);
		        GL.TexCoordPointer(2, TexCoordPointerType.Float, BlittableValueType.StrideOf(tex), tex);
 
		        GL.DrawArrays(BeginMode.Quads, 0, 4);
		        GL.Finish();    
			*/
			SwapBuffers();
			/*
			GL.DisableClientState(ArrayCap.VertexArray);
            GL.DisableClientState(ArrayCap.TextureCoordArray);
            */			
        }
 
		static int LoadTexture(string filename)
		{
		    if (String.IsNullOrEmpty(filename))
		        throw new ArgumentException(filename);
 
		    int id = GL.GenTexture();
		    GL.BindTexture(TextureTarget.Texture2D, id);
 
 
		    Bitmap bmp = new Bitmap(filename);
		    BitmapData bmp_data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
 
		    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp_data.Width, bmp_data.Height, 0,
		        OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0);
 
		    bmp.UnlockBits(bmp_data);
 
		    // We haven't uploaded mipmaps, so disable mipmapping (otherwise the texture will not appear).
		    // On newer video cards, we can use GL.GenerateMipmaps() or GL.Ext.GenerateMipmaps() to create
		    // mipmaps automatically. In that case, use TextureMinFilter.LinearMipmapLinear to enable them.
		    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
		    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
 
		    return id;
		}
 
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            // The 'using' idiom guarantees proper resource cleanup.
            // We request 30 UpdateFrame events per second, and unlimited
            // RenderFrame events (as fast as the computer can handle).
            using (Game game = new Game())
            {
                game.Run(30.0,  30.0);
            }
        }
    }
}

If I replace every Vector2 with Vector2h and Texture and Vertex Pointer Type to HalfFloat I get a crash. If I use Vector2h but Short as Pointer type it works fine, taking in account that the Texturecoordinates are scrambled.
Am I wrong or is this a bug?


Comments

Comment viewing options

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

Depends on the crash. Which is the actual function that crashes? What kind of exception is it throwing? Try adding a call to GL.GetError() before that function to see if anything abnormal is going on.

Goepfie's picture

GetError() returned NoError, but the failing function is TexCoordPointer/VertexPointer. Here is the complete Error console log:

NoError
 
Unhandled Exception: OpenTK.Graphics.GraphicsErrorException: InvalidEnum
  at OpenTK.Graphics.OpenGL.ErrorHelper.CheckErrors () [0x000bd] in .../Source/OpenTK/Graphics/OpenGL/ErrorHelper.cs:118 
  at OpenTK.Graphics.OpenGL.ErrorHelper.Dispose () [0x00000] in .../Source/OpenTK/Graphics/OpenGL/ErrorHelper.cs:129 
  at OpenTK.Graphics.OpenGL.GL.TexCoordPointer (Int32 size, TexCoordPointerType type, Int32 stride, IntPtr pointer) [0x0000c] in .../Source/OpenTK/Graphics/OpenGL/GL.cs:95839 
  at OpenTK.Graphics.OpenGL.GL.TexCoordPointer (Int32 size, TexCoordPointerType type, Int32 stride, Int32 offset) [0x00000] in .../Source/OpenTK/Graphics/OpenGL/GLHelper.cs:807 
  at StarterKit.Game.OnRenderFrame (OpenTK.FrameEventArgs e) [0x000ac] in .../testing/core/Main.cs:154 
  at OpenTK.GameWindow.OnRenderFrameInternal (OpenTK.FrameEventArgs e) [0x00016] in .../Source/OpenTK/GameWindow.cs:1041 
  at OpenTK.GameWindow.RaiseRenderFrame (System.Diagnostics.Stopwatch render_watch, System.Double& next_render, OpenTK.FrameEventArgs render_args) [0x00104] in.../Source/OpenTK/GameWindow.cs:527 
  at OpenTK.GameWindow.DispatchUpdateAndRenderFrame (System.Object sender, System.EventArgs e) [0x00018] in.../Source/OpenTK/GameWindow.cs:433 
  at OpenTK.GameWindow.Run (Double updates_per_second, Double frames_per_second) [0x000d5] in /.../Source/OpenTK/GameWindow.cs:411 
  at StarterKit.Game.Main () [0x00006].../testing/core/Main.cs:235 
X Error of failed request:  BadWindow (invalid Window parameter)
  Major opcode of failed request:  20 (X_GetProperty)
  Resource id in failed request:  0x4600002
  Serial number of failed request:  65
  Current serial number in output stream:  65
the Fiddler's picture

This indicates that your video card does not support the half datatype. You need to ensure that "GL_ARB_half_float_vertex" appears in the extension strings (i.e. in GL.GetString(StringName.Extensions)) before using any relevant tokens / functions.

All video cards supporting OpenGL 3 / DirectX 10 should support this extension, given recent enough drivers.

Goepfie's picture

I checked the Version and the extensions of my Hardware. It is running on OpenGL 1.4 and is not capable of GL_ARB_half_float_vertex ( At first i confused it with GL_ARB_half_float_pixel).

Thank you very much for your support and your time!