Icefox's picture

VBO Texturing Issues

All right, I seem to have reached the end of my patience with this, so I'm finally giving in and asking for help. I have a test program that should draw a couple textured triangles with vertex buffer objects, and it works great up until I try to actually make the texturing work, whereupon it dies with the following error:

Unhandled Exception: OpenTK.Graphics.GraphicsErrorException: OutOfMemory
at OpenTK.Graphics.OpenGL.ErrorHelper.CheckErrors()
at OpenTK.Graphics.OpenGL.ErrorHelper.Dispose()
at OpenTK.Graphics.OpenGL.GL.DrawArrays(BeginMode mode, Int32 first, Int32 count)
at OpenTKTest.VBOTest3.OnRenderFrame(FrameEventArgs e) in c:\Simon\dev\monodevelop projects\opentk test\opentk test\VBOTest3.cs:line 139
at OpenTK.GameWindow.OnRenderFrameInternal(FrameEventArgs e)
at OpenTK.GameWindow.RaiseRenderFrame(Stopwatch render_watch, Double& next_render, FrameEventArgs render_args)
at OpenTK.GameWindow.DispatchUpdateAndRenderFrame(Object sender, EventArgs e)
at OpenTK.GameWindow.Run(Double updates_per_second, Double frames_per_second)

My (somewhat janky experimental) code is below... sadly, I do not know enough about OpenGL (yet) to know whether this is a bug in OpenTK or if I'm just doing something terribly wrong. It does the same thing on the DrawElements() call though, and works fine (well, successfully draws black triangles) if I comment out the GL.EnableClientState(EnableCap.TextureCoordArray). I'm somewhat surprised that GL.DrawArrays() allocates memory at all, really.

I am using .NET 3.5 and OpenTK 1.0-beta2, compiled in debug mode.

using System;
using System.Windows.Forms;
 
using OpenTK;
using OpenTK.Graphics.OpenGL;
 
 
namespace OpenTKTest
{
	class VBOTest3 : GameWindow
	{
		float[] VBOVerts = new float[]{1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f};
		float[] VBOColors = new float[]{1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
		float[] VBOTexCoords = new float[]{1.0f, 0.0f, 0.0f, 1.0f, 0.5f, 0.5f, 0.25f, 1.25f, 0.25f};
		uint[] VBOIndices = new uint[]{1, 2, 0};
		uint bHandle, iHandle, cHandle, tcHandle;
		int vShaderHandle, fShaderHandle, programHandle, texHandle;
		// Trivial shaders.
		string vShaderSource = @"
void main() {
	gl_FrontColor = gl_Color;
	gl_Position = ftransform();
	gl_TexCoord[0]  = gl_MultiTexCoord0;
}
";
		string fShaderSource = @"
uniform sampler2D tex;
void main() {
	gl_FragColor = texture2D(tex, gl_TexCoord[0].st);
}
";
 
		public VBOTest3() : base(800,600, new OpenTK.Graphics.GraphicsMode(), "Vertex Buffer Test 3") {}
 
		int[] MakeTex()
		{
			// Excessively large, just in case.
			int[] b = new int[500];
			for(int i = 0; i < b.Length; i++)
			{
				b[i] = i;
			}
			return b;
		}
 
		protected override void OnLoad (EventArgs e)
		{
			base.OnLoad (e);
			GL.EnableClientState(EnableCap.VertexArray);
			GL.EnableClientState(EnableCap.ColorArray);
			GL.EnableClientState(EnableCap.TextureCoordArray);
			GL.Enable(EnableCap.DepthTest);
			GL.Enable(EnableCap.Texture2D);
 
			GL.GenBuffers(1, out bHandle);
			GL.BindBuffer(BufferTarget.ArrayBuffer, bHandle);
			GL.BufferData<float>(BufferTarget.ArrayBuffer, (IntPtr) (sizeof(float)*VBOVerts.Length),
			                     VBOVerts, BufferUsageHint.StaticDraw);
 
			GL.GenBuffers(1, out iHandle);
			GL.BindBuffer(BufferTarget.ElementArrayBuffer, iHandle);
			GL.BufferData<uint>(BufferTarget.ElementArrayBuffer, (IntPtr) (sizeof(uint)*VBOIndices.Length),
			                    VBOIndices, BufferUsageHint.StaticDraw);
 
			GL.GenBuffers(1, out cHandle);
			GL.BindBuffer(BufferTarget.ArrayBuffer, cHandle);
			GL.BufferData<float>(BufferTarget.ArrayBuffer, (IntPtr) (sizeof(float)*VBOColors.Length),
			                     VBOColors, BufferUsageHint.StaticDraw);
 
			GL.GenBuffers(1, out tcHandle);
			GL.BindBuffer(BufferTarget.ArrayBuffer, cHandle);
			GL.BufferData<float>(BufferTarget.ArrayBuffer, (IntPtr) (sizeof(float)*VBOTexCoords.Length),
			                     VBOTexCoords, BufferUsageHint.StaticDraw);
			int o;
			GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out o);
			Console.WriteLine("BufferSize: {0}", o);
 
 
			texHandle = GL.GenTexture();
			GL.ActiveTexture(TextureUnit.Texture0);
			GL.ClientActiveTexture(TextureUnit.Texture0);
			GL.BindTexture(TextureTarget.Texture2D, texHandle);
			GL.TexImage2D<int>(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb32i, 10, 10, 0, PixelFormat.Rgba,
			                   PixelType.Int, MakeTex());
 
			vShaderHandle = GL.CreateShader(ShaderType.VertexShader);
			fShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
 
			GL.ShaderSource(vShaderHandle, vShaderSource);
			GL.ShaderSource(fShaderHandle, fShaderSource);
			GL.CompileShader(vShaderHandle);
			GL.CompileShader(fShaderHandle);
			Console.Write(GL.GetShaderInfoLog(vShaderHandle));
			Console.Write(GL.GetShaderInfoLog(fShaderHandle));
 
			programHandle = GL.CreateProgram();
			GL.AttachShader(programHandle, vShaderHandle);
			GL.AttachShader(programHandle, fShaderHandle);
			GL.LinkProgram(programHandle);
 
			GL.UseProgram(programHandle);
 
			GL.ClearColor(System.Drawing.Color.MidnightBlue);
		}
 
		protected override void OnUnload(EventArgs e)
		{
			base.OnUnload(e);
		}
 
		protected override void OnResize(EventArgs e)
		{
			base.OnResize(e);
		}
 
		protected override void OnUpdateFrame(FrameEventArgs e)
		{
			base.OnUpdateFrame(e);
		}
 
		protected override void OnRenderFrame(FrameEventArgs e)
		{
			GL.Viewport(0, 0, Width, Height);
			Matrix4 lookat = Matrix4.LookAt(1, 1, 1, 1, 0, 0, 1, 0, 0);
			GL.MatrixMode(MatrixMode.Modelview);
			GL.LoadMatrix(ref lookat);
			GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
			GL.BindTexture(TextureTarget.Texture2D, texHandle);
 
			GL.BindBuffer(BufferTarget.ArrayBuffer, cHandle);
			GL.ColorPointer(3, ColorPointerType.Float, 0, IntPtr.Zero);
			GL.BindBuffer(BufferTarget.ArrayBuffer, bHandle);
			GL.VertexPointer(3, VertexPointerType.Float, 0, IntPtr.Zero);
			GL.BindBuffer(BufferTarget.ArrayBuffer, tcHandle);
			GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, IntPtr.Zero);
			GL.DrawArrays(BeginMode.Triangles, 0, 9);
 
			GL.Translate(0, 1, 0);
 
			GL.BindBuffer(BufferTarget.ArrayBuffer, bHandle);
			GL.VertexPointer(3, VertexPointerType.Float, 0, IntPtr.Zero);
			GL.BindBuffer(BufferTarget.ArrayBuffer, tcHandle);
			GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, IntPtr.Zero);
			GL.BindBuffer(BufferTarget.ElementArrayBuffer, iHandle);
 
			GL.DrawElements(BeginMode.Triangles, 3, DrawElementsType.UnsignedInt, IntPtr.Zero);
 
			SwapBuffers();
		}
 
		[STAThread]
		public static void Main()
		{
			using(VBOTest3 t = new VBOTest3())
			{
				t.Run(10.0,1.0);
			}
		}
	}
}

Comments

Comment viewing options

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

You are drawing 9 vertices, specified each having 3 float color, 3 float pos & 2 float textcoords.
But the buffers you provided contain 9 floats each *instead of* 27, 27 & 18 floats. Hence you are causing access violation.

Advice: when you are just starting, take an already working example first and play with it before making your own tries.

aik6980's picture

if you dont know OpenGL, but have a good knowledge of C++
here is an awesome GL tutorial,

http://nehe.gamedev.net/

it should help you get to understand OpenGL better, including underlying concept. Surely the code is C++ but you will be able to translate it not very difficult