vmelkon's picture

VB.NET and interleaving problem

Rendering with immediate code works, however that was only a test. I need to render my vertex structure with regular vertex arrays.
glGetError() returns 0, so there is no error.
I have posted the entire code but the relevant part starts with Call GL.EnableClientState(ArrayCap.VertexArray).

Also notice my "Structure TVertex_VNTC"
and
"Public Structure TVertex_VNTC2".

Imports OpenTK
Imports OpenTK.GLControl
Imports OpenTK.Platform
Imports OpenTK.Graphics.OpenGL
 
Public Class Form1
 
    Public Structure TVertex_VNTC
        Dim x As Single
        Dim y As Single
        Dim z As Single
        Dim nx As Single
        Dim ny As Single
        Dim nz As Single
        Dim S As Single
        Dim T As Single
        Dim mcolor As Color
        Dim garbage0 As Single
        Dim garbage1 As Single
        Dim garbage2 As Single
        Dim garbage3 As Single
        Dim garbage4 As Single
        Dim garbage5 As Single
    End Structure
 
    Public Structure TVertex_VNTC2
        Dim x As Single
        Dim y As Single
        Dim z As Single
        Dim nx As Single
        Dim ny As Single
        Dim nz As Single
        Dim S As Single
        Dim T As Single
        Dim red As Byte
        Dim green As Byte
        Dim blue As Byte
        Dim alpha As Byte
        Dim garbage0 As Single
        Dim garbage1 As Single
        Dim garbage2 As Single
        Dim garbage3 As Single
        Dim garbage4 As Single
        Dim garbage5 As Single
    End Structure
 
 
    Private MyTextureID As Integer
 
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim TextureID As Integer
 
 
        TextureID = 100
        GL.GenTextures(1, TextureID)
 
        GL.DeleteTextures(1, TextureID)
 
        Dim res() As String = GetType(Form1).Assembly.GetManifestResourceNames()
        PictureBox1.Image = New System.Drawing.Bitmap(GetType(Form1).Assembly.GetManifestResourceStream(res(2)))
 
        CreateFontTexture(MyTextureID)
 
    End Sub
 
    Private Sub GlControl1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles GlControl1.Paint
        Dim pVertex(4) As TVertex_VNTC2
        Dim pIndex16Bit(6) As Short
 
        GL.ClearColor(1.0, 1.0, 0.0, 0.0)
        GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit)
 
        GL.Color4(1.4F, 1.4F, 1.0F, 0.0F)
 
        GL.BindTexture(TextureTarget.Texture2D, MyTextureID)
        GL.Enable(EnableCap.Texture2D)
 
        pVertex(0).x = -1.0F
        pVertex(0).y = -1.0F
        pVertex(0).z = 0.5F
        pVertex(0).S = 0.0F
        pVertex(0).T = 0.0F
        pVertex(0).nx = 0.0F
        pVertex(0).ny = 0.0F
        pVertex(0).nz = 0.0F
        'pVertex(0).mcolor = Color.FromArgb(CType(255, Byte), CType(255, Byte), CType(255, Byte), CType(255, Byte))
        pVertex(0).red = 255
        pVertex(0).green = 255
        pVertex(0).blue = 255
        pVertex(0).alpha = 255
 
        pVertex(1).x = 1.0F
        pVertex(1).y = -1.0F
        pVertex(1).z = 0.5F
        pVertex(1).S = 1.0F
        pVertex(1).T = 0.0F
        pVertex(1).nx = 0.0F
        pVertex(1).ny = 0.0F
        pVertex(1).nz = 0.0F
        'pVertex(1).mcolor = Color.FromArgb(CType(255, Byte), CType(255, Byte), CType(255, Byte), CType(255, Byte))
        pVertex(1).red = 255
        pVertex(1).green = 255
        pVertex(1).blue = 255
        pVertex(1).alpha = 255
 
        pVertex(2).x = -1.0F
        pVertex(2).y = 1.0F
        pVertex(2).z = 0.5F
        pVertex(2).S = 0.0F
        pVertex(2).T = 1.0F
        pVertex(2).nx = 0.0F
        pVertex(2).ny = 0.0F
        pVertex(2).nz = 0.0F
        'pVertex(2).mcolor = Color.FromArgb(CType(255, Byte), CType(255, Byte), CType(255, Byte), CType(255, Byte))
        pVertex(2).red = 255
        pVertex(2).green = 255
        pVertex(2).blue = 255
        pVertex(2).alpha = 255
 
        pVertex(3).x = 1.0F
        pVertex(3).y = 1.0F
        pVertex(3).z = 0.5F
        pVertex(3).S = 1.0F
        pVertex(3).T = 1.0F
        pVertex(3).nx = 0.0F
        pVertex(3).ny = 0.0F
        pVertex(3).nz = 0.0F
        'pVertex(3).mcolor = Color.FromArgb(CType(255, Byte), CType(255, Byte), CType(255, Byte), CType(255, Byte))
        pVertex(3).red = 255
        pVertex(3).green = 255
        pVertex(3).blue = 255
        pVertex(3).alpha = 255
 
        pIndex16Bit(0) = 0
        pIndex16Bit(1) = 1
        pIndex16Bit(2) = 2
        pIndex16Bit(3) = 2
        pIndex16Bit(4) = 1
        pIndex16Bit(5) = 3
 
 
#If 0 Then
        GL.Begin(BeginMode.Quads)
 
        GL.TexCoord2(0.0, 0.0)
        GL.Vertex3(-1.0F, -1.0F, 0.5F)
        GL.TexCoord2(0.0, 1.0)
        GL.Vertex3(1.0F, -1.0F, 0.5F)
        GL.TexCoord2(1.0, 1.0)
        GL.Vertex3(1.0F, 1.0F, 1.0F)
        GL.TexCoord2(1.0, 0.0)
        GL.Vertex3(-1.0F, 1.0F, 1.0F)
 
        GL.End()
#End If
 
        Call GL.Disable(EnableCap.CullFace)
 
        Call GL.EnableClientState(ArrayCap.VertexArray)
        Call GL.EnableClientState(ArrayCap.NormalArray)
        Call GL.EnableClientState(ArrayCap.TextureCoordArray)
        Call GL.EnableClientState(ArrayCap.ColorArray)
 
        Dim q = System.Runtime.InteropServices.Marshal.SizeOf(pVertex(0))
        Call GL.VertexPointer(3, VertexPointerType.Float, q, pVertex(0).x)
        Call GL.NormalPointer(NormalPointerType.Float, q, pVertex(0).nx)
        Call GL.TexCoordPointer(2, TexCoordPointerType.Float, q, pVertex(0).S)
        '        Call GL.ColorPointer(4, ColorPointerType.UnsignedByte, q, pVertex(0).mcolor.R)
        Call GL.ColorPointer(4, ColorPointerType.UnsignedByte, q, pVertex(0).red)
 
        Call GL.DrawElements(BeginMode.Triangles, 6, DrawElementsType.UnsignedShort, pIndex16Bit(0))
 
        Dim ddd = GL.GetError()
 
        GlControl1.SwapBuffers()
 
    End Sub
 
    Private Sub GlControl1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles GlControl1.Resize
        'Dim glrc As HGLRC
        'glrc = wglGetCurrentContext()
        ResizeGL()
    End Sub
 
    Private Sub ResizeGL()
        GL.Viewport(0, 0, GlControl1.Width, GlControl1.Height)
        GL.MatrixMode(MatrixMode.Projection) ' Select The Projection Matrix
        GL.MatrixMode(MatrixMode.Modelview) ' Select The Modelview Matrix
        GL.LoadIdentity() ' Reset The Modelview Matrix
    End Sub
 
 
    Private Sub CreateFontTexture(ByRef textureid As Integer)
        'Dim textureid As Integer
        Dim bmp As Bitmap
        'Dim gfx As Graphics
        Dim data As System.Drawing.Imaging.BitmapData
        Dim res() As String = GetType(Form1).Assembly.GetManifestResourceNames()
 
        Call GL.GenTextures(1, textureid)
        Call GL.BindTexture(TextureTarget.Texture2D, textureid)
        'Call GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero)
        Call GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, TextureMinFilter.Linear)
        Call GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, TextureMagFilter.Linear)
 
        'Get the bitmap resource into this picture box control
        'The picture control has been made non-visible using its the IDE
        'PictureBox1.Image = New System.Drawing.Bitmap(GetType(Form1).Assembly.GetManifestResourceStream(res(2)))
        bmp = New System.Drawing.Bitmap(GetType(Form1).Assembly.GetManifestResourceStream(res(1)))
 
        'PictureBox1.Image.
 
        'bmp = New Bitmap(width, height)
        'bmp.
        'gfx = Graphics.FromImage(bmp)
 
        ' Use gfx.DrawString() to print the characters you need
 
        'Upload bmp into the OpenGL texture
        data = bmp.LockBits( _
           New System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), _
           System.Drawing.Imaging.ImageLockMode.ReadOnly, _
           System.Drawing.Imaging.PixelFormat.Format32bppArgb)
 
        'GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, bmp.Width, bmp.Height, PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0)
        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp.Width, bmp.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0)
        Call bmp.UnlockBits(data)
    End Sub
 
 
End Class

Comments

Comment viewing options

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

Vertex arrays will not work correctly in .Net, unless you pin the arrays. Don't do that: use vertex buffer objects instead!

vmelkon's picture

I can't because I have to use GL 1.1

the Fiddler's picture

In that case, either pin the arrays after you create them:

GCHandle.Alloc(pVertex, GCHandleType.Pinned)

or, if the data is immutable, use display lists which don't suffer from this issue.

vmelkon's picture

What exactly is "pinned". Does the array move around because of some memory allocator?

Also, I am declaring the array on the stack. I don't see why the array's location would change between a call from
glVertexPointer and glDrawElements. It could even cause a crash.

the Fiddler's picture

Managed arrays are always allocated on the heap in .Net.

The .Net GC is a compacting garbage collector, which means it will move memory around to improve performance. This is perfectly fine in pure .Net programs, where the collector knows precisely where each piece of memory lies and ensures that all memory references are valid.

Once you pass a managed piece of memory to unmanaged code, however, these guarantees go out the window. This can cause crashes if you are not careful, which is why Vertex Arrays are generally not recommended (VBOs and display lists do not suffer from this issue). The solution is to either (a) pin the memory yourself for as long as the unmanaged code will be using it or (b) allocate unmanaged memory via Marshal.AllocHGlobal() and store your arrays there (the second solution is rather annoying to use, since you have to use Marshal.Read/Write*() methods to access those arrays).

vmelkon's picture

Ok, so I tried 1 VBO and 1 IBO and it still is not rendering.

Imports OpenTK
Imports OpenTK.GLControl
Imports OpenTK.Platform
Imports OpenTK.Graphics.OpenGL
Imports System.Runtime.InteropServices
 
Public Class Form1
 
    Public Structure TVertex_VNTC
        Dim x As Single
        Dim y As Single
        Dim z As Single
        Dim nx As Single
        Dim ny As Single
        Dim nz As Single
        Dim S As Single
        Dim T As Single
        Dim mcolor As Color
        Dim garbage0 As Single
        Dim garbage1 As Single
        Dim garbage2 As Single
        Dim garbage3 As Single
        Dim garbage4 As Single
        Dim garbage5 As Single
    End Structure
 
    Public Structure TVertex_VNTC2
        Dim x As Single
        Dim y As Single
        Dim z As Single
        Dim nx As Single
        Dim ny As Single
        Dim nz As Single
        Dim S As Single
        Dim T As Single
        Dim red As Byte
        Dim green As Byte
        Dim blue As Byte
        Dim alpha As Byte
        Dim garbage0 As Single
        Dim garbage1 As Single
        Dim garbage2 As Single
        Dim garbage3 As Single
        Dim garbage4 As Single
        Dim garbage5 As Single
    End Structure
 
 
    Private MyTextureID As Integer
 
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim TextureID As Integer
 
 
        TextureID = 100
        GL.GenTextures(1, TextureID)
 
        GL.DeleteTextures(1, TextureID)
 
        Dim res() As String = GetType(Form1).Assembly.GetManifestResourceNames()
        PictureBox1.Image = New System.Drawing.Bitmap(GetType(Form1).Assembly.GetManifestResourceStream(res(2)))
 
        CreateFontTexture(MyTextureID)
 
        Call GL.ShadeModel(ShadingModel.Smooth)
 
    End Sub
 
    Private Sub GlControl1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles GlControl1.Paint
        Dim pVertex(4) As TVertex_VNTC2
        Dim pIndex16Bit(6) As Integer
        Dim pvv(12) As Single
        Dim ptt(8) As Single
        Dim gh As GCHandle
        Dim MyPointer As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pVertex(0)) * 4)
 
        GL.ClearColor(1.0, 1.0, 0.5, 0.0)
        GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit)
 
        GL.Color4(1.4F, 1.4F, 1.0F, 0.0F)
 
        GL.BindTexture(TextureTarget.Texture2D, MyTextureID)
        GL.Enable(EnableCap.Texture2D)
 
        pvv = New Single() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
 
        pVertex(0).x = pvv(0) = -1.0F
        pVertex(0).y = pvv(1) = -1.0F
        pVertex(0).z = pvv(2) = 0.5F
        pVertex(0).S = ptt(0) = 0.0F
        pVertex(0).T = ptt(1) = 0.0F
        pVertex(0).nx = 0.0F
        pVertex(0).ny = 0.0F
        pVertex(0).nz = 0.0F
        'pVertex(0).mcolor = Color.FromArgb(CType(255, Byte), CType(255, Byte), CType(255, Byte), CType(255, Byte))
        pVertex(0).red = 0
        pVertex(0).green = 0
        pVertex(0).blue = 0
        pVertex(0).alpha = 255
 
        pVertex(1).x = pvv(3) = 1.0F
        pVertex(1).y = pvv(4) = -1.0F
        pVertex(1).z = pvv(5) = 0.5F
        pVertex(1).S = ptt(2) = 1.0F
        pVertex(1).T = ptt(3) = 0.0F
        pVertex(1).nx = 0.0F
        pVertex(1).ny = 0.0F
        pVertex(1).nz = 0.0F
        'pVertex(1).mcolor = Color.FromArgb(CType(255, Byte), CType(255, Byte), CType(255, Byte), CType(255, Byte))
        pVertex(1).red = 255
        pVertex(1).green = 255
        pVertex(1).blue = 255
        pVertex(1).alpha = 255
 
        pVertex(2).x = pvv(6) = -1.0F
        pVertex(2).y = pvv(7) = 1.0F
        pVertex(2).z = pvv(8) = 1.0F
        pVertex(2).S = ptt(4) = 0.0F
        pVertex(2).T = ptt(5) = 1.0F
        pVertex(2).nx = 0.0F
        pVertex(2).ny = 0.0F
        pVertex(2).nz = 0.0F
        'pVertex(2).mcolor = Color.FromArgb(CType(255, Byte), CType(255, Byte), CType(255, Byte), CType(255, Byte))
        pVertex(2).red = 255
        pVertex(2).green = 255
        pVertex(2).blue = 255
        pVertex(2).alpha = 255
 
        pVertex(3).x = pvv(9) = 1.0F
        pVertex(3).y = pvv(10) = 1.0F
        pVertex(3).z = pvv(11) = 1.0F
        pVertex(3).S = ptt(6) = 1.0F
        pVertex(3).T = ptt(7) = 1.0F
        pVertex(3).nx = 0.0F
        pVertex(3).ny = 0.0F
        pVertex(3).nz = 0.0F
        'pVertex(3).mcolor = Color.FromArgb(CType(255, Byte), CType(255, Byte), CType(255, Byte), CType(255, Byte))
        pVertex(3).red = 255
        pVertex(3).green = 255
        pVertex(3).blue = 255
        pVertex(3).alpha = 255
 
        'Marshal.StructureToPtr(pVertex, MyPointer, False)
 
        pIndex16Bit(0) = 0
        pIndex16Bit(1) = 1
        pIndex16Bit(2) = 2
        pIndex16Bit(3) = 2
        pIndex16Bit(4) = 1
        pIndex16Bit(5) = 3
 
 
#If 0 Then
        GL.Begin(BeginMode.Quads)
 
        GL.TexCoord2(0.0, 0.0)
        GL.Vertex3(-1.0F, -1.0F, 0.5F)
        GL.TexCoord2(0.0, 1.0)
        GL.Vertex3(1.0F, -1.0F, 0.5F)
        GL.TexCoord2(1.0, 1.0)
        GL.Vertex3(1.0F, 1.0F, 1.0F)
        GL.TexCoord2(1.0, 0.0)
        GL.Vertex3(-1.0F, 1.0F, 1.0F)
 
        GL.End()
#End If
 
        Call GL.Disable(EnableCap.CullFace)
 
        Call GL.EnableClientState(ArrayCap.VertexArray)
        Call GL.EnableClientState(ArrayCap.NormalArray)
        Call GL.EnableClientState(ArrayCap.TextureCoordArray)
        Call GL.EnableClientState(ArrayCap.ColorArray)
 
        Dim q = System.Runtime.InteropServices.Marshal.SizeOf(pVertex(0))
        Call GL.VertexPointer(3, VertexPointerType.Float, q, pVertex(0).x)
        Call GL.NormalPointer(NormalPointerType.Float, q, pVertex(0).nx)
        Call GL.TexCoordPointer(2, TexCoordPointerType.Float, q, pVertex(0).S)
        '        Call GL.ColorPointer(4, ColorPointerType.UnsignedByte, q, pVertex(0).mcolor.R)
        Call GL.ColorPointer(4, ColorPointerType.UnsignedByte, q, pVertex(0).red)
 
        Call GL.DisableClientState(ArrayCap.NormalArray)
        Call GL.DisableClientState(ArrayCap.TextureCoordArray)
        Call GL.DisableClientState(ArrayCap.ColorArray)
        Call GL.VertexPointer(3, VertexPointerType.Float, 0, pvv)
        Call GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, ptt)
 
        Dim vboid As Integer
        Call GL.GenBuffers(1, vboid)
        Call GL.BindBuffer(BufferTarget.ArrayBuffer, vboid)
        Call GL.BufferData(BufferTarget.ArrayBuffer, q * 4, pVertex, BufferUsageHint.StaticDraw)
 
        Dim iboid As Integer
        Call GL.GenBuffers(1, iboid)
        Call GL.BindBuffer(BufferTarget.ElementArrayBuffer, iboid)
        Call GL.BufferData(BufferTarget.ElementArrayBuffer, 4 * 6, pIndex16Bit, BufferUsageHint.StaticDraw)
 
        Call GL.VertexPointer(3, VertexPointerType.Float, 0, 0)
 
        Call GL.DrawElements(BeginMode.Triangles, 6, DrawElementsType.UnsignedInt, 0)
 
        Dim ddd = GL.GetError()
 
        GlControl1.SwapBuffers()
 
    End Sub
 
    Private Sub GlControl1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles GlControl1.Resize
        'Dim glrc As HGLRC
        'glrc = wglGetCurrentContext()
        ResizeGL()
    End Sub
 
    Private Sub ResizeGL()
        GL.Viewport(0, 0, GlControl1.Width, GlControl1.Height)
        GL.MatrixMode(MatrixMode.Projection) ' Select The Projection Matrix
        GL.MatrixMode(MatrixMode.Modelview) ' Select The Modelview Matrix
        GL.LoadIdentity() ' Reset The Modelview Matrix
    End Sub
 
 
    Private Sub CreateFontTexture(ByRef textureid As Integer)
        'Dim textureid As Integer
        Dim bmp As Bitmap
        'Dim gfx As Graphics
        Dim data As System.Drawing.Imaging.BitmapData
        Dim res() As String = GetType(Form1).Assembly.GetManifestResourceNames()
 
        Call GL.GenTextures(1, textureid)
        Call GL.BindTexture(TextureTarget.Texture2D, textureid)
        'Call GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero)
        Call GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, TextureMinFilter.Linear)
        Call GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, TextureMagFilter.Linear)
 
        'Get the bitmap resource into this picture box control
        'The picture control has been made non-visible using its the IDE
        'PictureBox1.Image = New System.Drawing.Bitmap(GetType(Form1).Assembly.GetManifestResourceStream(res(2)))
        bmp = New System.Drawing.Bitmap(GetType(Form1).Assembly.GetManifestResourceStream(res(2)))
 
        'PictureBox1.Image.
 
        'bmp = New Bitmap(width, height)
        'bmp.
        'gfx = Graphics.FromImage(bmp)
 
        ' Use gfx.DrawString() to print the characters you need
 
        'Upload bmp into the OpenGL texture
        data = bmp.LockBits( _
           New System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), _
           System.Drawing.Imaging.ImageLockMode.ReadOnly, _
           System.Drawing.Imaging.PixelFormat.Format32bppArgb)
 
        'GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, bmp.Width, bmp.Height, PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0)
        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp.Width, bmp.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0)
        Call bmp.UnlockBits(data)
    End Sub
 
 
End Class
the Fiddler's picture

You are not specifying texcoord and color offsets for the VBO code.

Check the "VBO Static" sample in the OpenTK Example Browser.

vmelkon's picture

You are right, I was uploading pVertex
I changed
Call GL.BufferData(BufferTarget.ArrayBuffer, q * 4, pVertex, BufferUsageHint.StaticDraw)
to
Call GL.BufferData(BufferTarget.ArrayBuffer, 12 * 4, pvv, BufferUsageHint.StaticDraw)

and also
Call GL.VertexPointer(3, VertexPointerType.Float, 12, New IntPtr(0))
Call GL.DrawElements(BeginMode.Triangles, 6, DrawElementsType.UnsignedInt, IntPtr.Zero)

I'm not using texcoord or color.

Still not getting any triangles and glGetError() returns 0.

vmelkon's picture

I use GLIntercept to see what is happening.
**** Never mind, there is some sort of problem with GLIntercept

the Fiddler's picture

Try gDEBugger. They offer a free download now and it generally works better than glIntercept.