Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

#ActualScourage

Posted 22 October 2012 - 08:54 AM

There's a couple of things that strike me as odd:

-you're recreating the VBO every render call.  Not a big deal in this particular case, but you will want to fill it up once and then just render it each frame.
-you're not loading a model view matrix.  I recommend just starting with an identity matrix.
-looks like you're drawing your triangles in clockwise order, but they should be counter clockwise, either swap the verts or the indices to make it draw in counter clockwise order

Here's my VBO class from a project that is similar to yours.  Maybe you can use this to help troubleshoot, or just use however you want

using System;
using System.Runtime.InteropServices;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
namespace SimEngine
{
   [StructLayout(LayoutKind.Sequential)]
   public struct Vertex
   {
	  public Vector3 Position;
	  public Vector3 Normal;
	  public Vector2 TexCoord;
	  public static readonly int Stride = Marshal.SizeOf(default(Vertex));
   }
   public class VertexBuffer
   {
	  public int myVertexId;
	  public int myIndexId;
	  public BeginMode myMode=BeginMode.Triangles;
	  public uint myVertexLength;
	  public uint myIndexLength;
	  int myDataOffset = 0;
	  int myByteOffset = 0;
	  public enum IndexType { USHORT, UINT};
	  IndexType myIndexType;
	  public VertexBuffer()
	  {
		 init();
	  }
	  public bool init()
	  {
		 GL.GenBuffers(1, out myVertexId);
		 GL.GenBuffers(1, out myIndexId);
		 return true;
	  }
	  public int vertexOffset
	  {
		 get { return myDataOffset; }
		 set { myDataOffset = value; myByteOffset = myDataOffset * Vertex.Stride; }
	  }
	  public void SetVertexData(Vertex[] data)
	  {
		 SetVertexData(data, (uint)data.Length);
	  }
	  public void SetVertexData(Vertex[] data, uint count)
	  {
		 if (data == null)
		    throw new ArgumentNullException("vertex data not found");
		 myVertexLength = count;
		 GL.BindBuffer(BufferTarget.ArrayBuffer, myVertexId);
		 GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(data.Length * Vertex.Stride), data, BufferUsageHint.StaticDraw);
	  }
	  public void SetIndexData(ushort[] data)
	  {
		 SetIndexData(data, (ushort)data.Length);
	  }
	  public void SetIndexData(ushort[] data, uint count)
	  {
		 if (data == null)
		    throw new ArgumentNullException("index data not found");
		
		 myIndexType = IndexType.USHORT;
		 myIndexLength = count;
		 GL.BindBuffer(BufferTarget.ElementArrayBuffer, myIndexId);
		 GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(data.Length * sizeof(ushort)), data, BufferUsageHint.DynamicDraw);
	  }
	  public void SetIndexData(uint[] data)
	  {
		 SetIndexData(data, (ushort)data.Length);
	  }
	  public void SetIndexData(uint[] data, uint count)
	  {
		 if (data == null)
		    throw new ArgumentNullException("index data not found");
		 myIndexType = IndexType.UINT;
		 myIndexLength = count;
		 GL.BindBuffer(BufferTarget.ElementArrayBuffer, myIndexId);
		 GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(data.Length * sizeof(uint)), data, BufferUsageHint.DynamicDraw);
	  }
	  public void renderRange(int offset, int count)
	  {
		 //we're binding the normals as colors here for visualizing the triangles
		 GL.EnableClientState(ArrayCap.VertexArray);
		 GL.EnableClientState(ArrayCap.NormalArray);
		 GL.EnableClientState(ArrayCap.TextureCoordArray);
		 GL.BindBuffer(BufferTarget.ArrayBuffer, myVertexId);
		 GL.BindBuffer(BufferTarget.ElementArrayBuffer, myIndexId);
		 GL.VertexPointer(3, VertexPointerType.Float, Vertex.Stride, new IntPtr(0 + myByteOffset));
		 GL.NormalPointer(NormalPointerType.Float, Vertex.Stride, new IntPtr(Vector3.SizeInBytes + myByteOffset));
		 GL.TexCoordPointer(2, TexCoordPointerType.Float, Vertex.Stride, new IntPtr(2 * Vector3.SizeInBytes + myByteOffset));
		 if (myIndexType == IndexType.USHORT)
		    GL.DrawRangeElements(myMode, 0, myIndexLength, count, DrawElementsType.UnsignedShort, new IntPtr(offset * 2));
		 else
		    GL.DrawRangeElements(myMode, 0, myIndexLength, count, DrawElementsType.UnsignedInt, new IntPtr(offset * 4));
		 GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
		 GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
		 GL.DisableClientState(ArrayCap.VertexArray);
		 GL.DisableClientState(ArrayCap.NormalArray);
		 GL.DisableClientState(ArrayCap.TextureCoordArray);
		 Draw.checkError("VBO::renderRange");
	  }
	 
	  public void render()
	  {
		 //we're binding the normals as colors here for visualizing the triangles
		 GL.EnableClientState(ArrayCap.VertexArray);
		 GL.EnableClientState(ArrayCap.NormalArray);
		 GL.EnableClientState(ArrayCap.TextureCoordArray);
		 GL.BindBuffer(BufferTarget.ArrayBuffer, myVertexId);
		 GL.BindBuffer(BufferTarget.ElementArrayBuffer, myIndexId);
		 GL.VertexPointer(3, VertexPointerType.Float, Vertex.Stride, new IntPtr(0 + myByteOffset));
		 GL.NormalPointer(NormalPointerType.Float, Vertex.Stride, new IntPtr(Vector3.SizeInBytes + myByteOffset));
		 GL.TexCoordPointer(2, TexCoordPointerType.Float, Vertex.Stride, new IntPtr(2 * Vector3.SizeInBytes + myByteOffset));
		 int batchSize = 63000; //multiple of 4 and 3
		 int count, rendered;
		 rendered = 0;
		 if (myIndexLength <= batchSize)
		 {
		    count = (int)myIndexLength;
		 }
		 else
		 {
		    count = batchSize;
		 }
		 while (rendered < myIndexLength)
		 {
		    if(myIndexType==IndexType.USHORT)
			   GL.DrawRangeElements(myMode, 0, myIndexLength, count, DrawElementsType.UnsignedShort, new IntPtr(rendered * 4));
		    else
			   GL.DrawRangeElements(myMode, 0, myIndexLength, count, DrawElementsType.UnsignedInt, new IntPtr(rendered * 4));
		    rendered += count;
		    if (myIndexLength - rendered < batchSize)
		    {
			   count = (int)myIndexLength - rendered;
		    }
		 }
		 GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
		 GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
		 GL.DisableClientState(ArrayCap.VertexArray);
		 GL.DisableClientState(ArrayCap.NormalArray);
		 GL.DisableClientState(ArrayCap.TextureCoordArray);
		 Draw.checkError("VBO::render");
	  }
   }
}

*edited for formating and took my copyright notice off, this code is free!

#2Scourage

Posted 22 October 2012 - 08:53 AM

There's a couple of things that strike me as odd:

-you're recreating the VBO every render call.  Not a big deal in this particular case, but you will want to fill it up once and then just render it each frame.
-you're not loading a model view matrix.  I recommend just starting with an identity matrix.
-looks like you're drawing your triangles in clockwise order, but they should be counter clockwise, either swap the verts or the indices to make it draw in counter clockwise order

Here's my VBO class from a project that is similar to yours.  Maybe you can use this to help troubleshoot, or just use however you want

[source lang="csharp"]using System;using System.Runtime.InteropServices;using OpenTK;using OpenTK.Graphics;using OpenTK.Graphics.OpenGL;namespace SimEngine{   [StructLayout(LayoutKind.Sequential)]   public struct Vertex   {   public Vector3 Position;   public Vector3 Normal;   public Vector2 TexCoord;   public static readonly int Stride = Marshal.SizeOf(default(Vertex));   }   public class VertexBuffer   {   public int myVertexId;   public int myIndexId;   public BeginMode myMode=BeginMode.Triangles;   public uint myVertexLength;   public uint myIndexLength;   int myDataOffset = 0;   int myByteOffset = 0;   public enum IndexType { USHORT, UINT};   IndexType myIndexType;   public VertexBuffer()   { init();   }   public bool init()   { GL.GenBuffers(1, out myVertexId); GL.GenBuffers(1, out myIndexId); return true;   }   public int vertexOffset   { get { return myDataOffset; } set { myDataOffset = value; myByteOffset = myDataOffset * Vertex.Stride; }   }   public void SetVertexData(Vertex[] data)   { SetVertexData(data, (uint)data.Length);   }   public void SetVertexData(Vertex[] data, uint count)   { if (data == null) throw new ArgumentNullException("vertex data not found"); myVertexLength = count; GL.BindBuffer(BufferTarget.ArrayBuffer, myVertexId); GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(data.Length * Vertex.Stride), data, BufferUsageHint.StaticDraw);   }   public void SetIndexData(ushort[] data)   { SetIndexData(data, (ushort)data.Length);   }   public void SetIndexData(ushort[] data, uint count)   { if (data == null) throw new ArgumentNullException("index data not found"); myIndexType = IndexType.USHORT; myIndexLength = count; GL.BindBuffer(BufferTarget.ElementArrayBuffer, myIndexId); GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(data.Length * sizeof(ushort)), data, BufferUsageHint.DynamicDraw);   }   public void SetIndexData(uint[] data)   { SetIndexData(data, (ushort)data.Length);   }   public void SetIndexData(uint[] data, uint count)   { if (data == null) throw new ArgumentNullException("index data not found"); myIndexType = IndexType.UINT; myIndexLength = count; GL.BindBuffer(BufferTarget.ElementArrayBuffer, myIndexId); GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(data.Length * sizeof(uint)), data, BufferUsageHint.DynamicDraw);   }   public void renderRange(int offset, int count)   { //we're binding the normals as colors here for visualizing the triangles GL.EnableClientState(ArrayCap.VertexArray); GL.EnableClientState(ArrayCap.NormalArray); GL.EnableClientState(ArrayCap.TextureCoordArray); GL.BindBuffer(BufferTarget.ArrayBuffer, myVertexId); GL.BindBuffer(BufferTarget.ElementArrayBuffer, myIndexId); GL.VertexPointer(3, VertexPointerType.Float, Vertex.Stride, new IntPtr(0 + myByteOffset)); GL.NormalPointer(NormalPointerType.Float, Vertex.Stride, new IntPtr(Vector3.SizeInBytes + myByteOffset)); GL.TexCoordPointer(2, TexCoordPointerType.Float, Vertex.Stride, new IntPtr(2 * Vector3.SizeInBytes + myByteOffset)); if (myIndexType == IndexType.USHORT) GL.DrawRangeElements(myMode, 0, myIndexLength, count, DrawElementsType.UnsignedShort, new IntPtr(offset * 2)); else GL.DrawRangeElements(myMode, 0, myIndexLength, count, DrawElementsType.UnsignedInt, new IntPtr(offset * 4)); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); GL.DisableClientState(ArrayCap.VertexArray); GL.DisableClientState(ArrayCap.NormalArray); GL.DisableClientState(ArrayCap.TextureCoordArray); Draw.checkError("VBO::renderRange");   }      public void render()   { //we're binding the normals as colors here for visualizing the triangles GL.EnableClientState(ArrayCap.VertexArray); GL.EnableClientState(ArrayCap.NormalArray); GL.EnableClientState(ArrayCap.TextureCoordArray); GL.BindBuffer(BufferTarget.ArrayBuffer, myVertexId); GL.BindBuffer(BufferTarget.ElementArrayBuffer, myIndexId); GL.VertexPointer(3, VertexPointerType.Float, Vertex.Stride, new IntPtr(0 + myByteOffset)); GL.NormalPointer(NormalPointerType.Float, Vertex.Stride, new IntPtr(Vector3.SizeInBytes + myByteOffset)); GL.TexCoordPointer(2, TexCoordPointerType.Float, Vertex.Stride, new IntPtr(2 * Vector3.SizeInBytes + myByteOffset)); int batchSize = 63000; //multiple of 4 and 3 int count, rendered; rendered = 0; if (myIndexLength <= batchSize) { count = (int)myIndexLength; } else { count = batchSize; } while (rendered < myIndexLength) { if(myIndexType==IndexType.USHORT)    GL.DrawRangeElements(myMode, 0, myIndexLength, count, DrawElementsType.UnsignedShort, new IntPtr(rendered * 4)); else    GL.DrawRangeElements(myMode, 0, myIndexLength, count, DrawElementsType.UnsignedInt, new IntPtr(rendered * 4)); rendered += count; if (myIndexLength - rendered < batchSize) {    count = (int)myIndexLength - rendered; } } GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); GL.DisableClientState(ArrayCap.VertexArray); GL.DisableClientState(ArrayCap.NormalArray); GL.DisableClientState(ArrayCap.TextureCoordArray); Draw.checkError("VBO::render");   }   }}[/source]

#1Scourage

Posted 22 October 2012 - 08:52 AM

There's a couple of things that strike me as odd:

-you're recreating the VBO every render call.  Not a big deal in this particular case, but you will want to fill it up once and then just render it each frame.
-you're not loading a model view matrix.  I recommend just starting with an identity matrix.
-looks like you're drawing your triangles in clockwise order, but they should be counter clockwise, either swap the verts or the indices to make it draw in counter clockwise order

Here's my VBO class from a project that is similar to yours.  Maybe you can use this to help troubleshoot, or just use however you want (I own the copyright and I'm willing to share)

[source lang="csharp"]*Copyright © 2012 Bionic Dog Studios, Bob HolcombAll rights reserved*/using System;using System.Runtime.InteropServices;using OpenTK;using OpenTK.Graphics;using OpenTK.Graphics.OpenGL;namespace SimEngine{   [StructLayout(LayoutKind.Sequential)]   public struct Vertex   {      public Vector3 Position;      public Vector3 Normal;      public Vector2 TexCoord;      public static readonly int Stride = Marshal.SizeOf(default(Vertex));   }   public class VertexBuffer   {      public int myVertexId;      public int myIndexId;      public BeginMode myMode=BeginMode.Triangles;      public uint myVertexLength;      public uint myIndexLength;      int myDataOffset = 0;      int myByteOffset = 0;      public enum IndexType { USHORT, UINT};      IndexType myIndexType;      public VertexBuffer()      {         init();      }      public bool init()      {         GL.GenBuffers(1, out myVertexId);         GL.GenBuffers(1, out myIndexId);         return true;      }      public int vertexOffset      {         get { return myDataOffset; }         set { myDataOffset = value; myByteOffset = myDataOffset * Vertex.Stride; }      }      public void SetVertexData(Vertex[] data)      {         SetVertexData(data, (uint)data.Length);      }      public void SetVertexData(Vertex[] data, uint count)      {         if (data == null)            throw new ArgumentNullException("vertex data not found");         myVertexLength = count;         GL.BindBuffer(BufferTarget.ArrayBuffer, myVertexId);         GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(data.Length * Vertex.Stride), data, BufferUsageHint.StaticDraw);      }      public void SetIndexData(ushort[] data)      {         SetIndexData(data, (ushort)data.Length);      }      public void SetIndexData(ushort[] data, uint count)      {         if (data == null)            throw new ArgumentNullException("index data not found");                  myIndexType = IndexType.USHORT;         myIndexLength = count;         GL.BindBuffer(BufferTarget.ElementArrayBuffer, myIndexId);         GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(data.Length * sizeof(ushort)), data, BufferUsageHint.DynamicDraw);      }      public void SetIndexData(uint[] data)      {         SetIndexData(data, (ushort)data.Length);      }      public void SetIndexData(uint[] data, uint count)      {         if (data == null)            throw new ArgumentNullException("index data not found");         myIndexType = IndexType.UINT;         myIndexLength = count;         GL.BindBuffer(BufferTarget.ElementArrayBuffer, myIndexId);         GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(data.Length * sizeof(uint)), data, BufferUsageHint.DynamicDraw);      }      public void renderRange(int offset, int count)      {         //we're binding the normals as colors here for visualizing the triangles         GL.EnableClientState(ArrayCap.VertexArray);         GL.EnableClientState(ArrayCap.NormalArray);         GL.EnableClientState(ArrayCap.TextureCoordArray);         GL.BindBuffer(BufferTarget.ArrayBuffer, myVertexId);         GL.BindBuffer(BufferTarget.ElementArrayBuffer, myIndexId);         GL.VertexPointer(3, VertexPointerType.Float, Vertex.Stride, new IntPtr(0 + myByteOffset));         GL.NormalPointer(NormalPointerType.Float, Vertex.Stride, new IntPtr(Vector3.SizeInBytes + myByteOffset));         GL.TexCoordPointer(2, TexCoordPointerType.Float, Vertex.Stride, new IntPtr(2 * Vector3.SizeInBytes + myByteOffset));         if (myIndexType == IndexType.USHORT)            GL.DrawRangeElements(myMode, 0, myIndexLength, count, DrawElementsType.UnsignedShort, new IntPtr(offset * 2));         else            GL.DrawRangeElements(myMode, 0, myIndexLength, count, DrawElementsType.UnsignedInt, new IntPtr(offset * 4));         GL.BindBuffer(BufferTarget.ArrayBuffer, 0);         GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);         GL.DisableClientState(ArrayCap.VertexArray);         GL.DisableClientState(ArrayCap.NormalArray);         GL.DisableClientState(ArrayCap.TextureCoordArray);         Draw.checkError("VBO::renderRange");      }            public void render()      {         //we're binding the normals as colors here for visualizing the triangles         GL.EnableClientState(ArrayCap.VertexArray);         GL.EnableClientState(ArrayCap.NormalArray);         GL.EnableClientState(ArrayCap.TextureCoordArray);         GL.BindBuffer(BufferTarget.ArrayBuffer, myVertexId);         GL.BindBuffer(BufferTarget.ElementArrayBuffer, myIndexId);         GL.VertexPointer(3, VertexPointerType.Float, Vertex.Stride, new IntPtr(0 + myByteOffset));         GL.NormalPointer(NormalPointerType.Float, Vertex.Stride, new IntPtr(Vector3.SizeInBytes + myByteOffset));         GL.TexCoordPointer(2, TexCoordPointerType.Float, Vertex.Stride, new IntPtr(2 * Vector3.SizeInBytes + myByteOffset));         int batchSize = 63000; //multiple of 4 and 3         int count, rendered;         rendered = 0;         if (myIndexLength <= batchSize)         {            count = (int)myIndexLength;         }         else         {            count = batchSize;         }         while (rendered < myIndexLength)         {            if(myIndexType==IndexType.USHORT)               GL.DrawRangeElements(myMode, 0, myIndexLength, count, DrawElementsType.UnsignedShort, new IntPtr(rendered * 4));            else               GL.DrawRangeElements(myMode, 0, myIndexLength, count, DrawElementsType.UnsignedInt, new IntPtr(rendered * 4));            rendered += count;            if (myIndexLength - rendered < batchSize)            {               count = (int)myIndexLength - rendered;            }         }         GL.BindBuffer(BufferTarget.ArrayBuffer, 0);         GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);         GL.DisableClientState(ArrayCap.VertexArray);         GL.DisableClientState(ArrayCap.NormalArray);         GL.DisableClientState(ArrayCap.TextureCoordArray);         Draw.checkError("VBO::render");      }   }}[/source]

PARTNERS