darkprinze's picture

[Solved] Scaling and translation is different when switched from immediate mode to VBO mode

I was using immediate mode to render the mesh but performance is poor, and i switched to VBO for better performance. I have bounding box size and center value, and using those value, i fit the mesh into center of the screen. It is working fine for immediate mode, but it looks different for VBO. Here is the code.

Code to fit model into center screen.

           // set bounding box length
            float d = 1.0f / dist; // dist is bounding box length
 
            // scale the model based on mesh length
            GL.Scale(d, d, d);            
 
            // set the mesh to center of the screen
            GL.Translate(-center); // center is calculated form bounding box
 
           // draw mesh
           ........

Code to draw the immediate mode and VBO mode

// immediate mode
 GL.Begin(PrimitiveType.Triangles);
            for (int i = 0; i < vertices.Count; i++)
            {               
                GL.Normal3(new Vector3d(X, Y,Z);               
                GL.Vertex3(new Vector3d(X, Y,Z));               
                GL.Vertex3(new Vector3d(X, Y,Z));               
                GL.Vertex3(new Vector3d(X, Y,Z));
            }
            GL.End();
 
// VBO mode
 
//load vbo
           GL.GenBuffers(1, out vbo);
            GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
            GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(data.Length * Vertex.Stride), data, BufferUsageHint.StaticDraw);
 
//  draw vbo
// enable client state
            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.NormalArray);
            //GL.EnableClientState(ArrayCap.TextureCoordArray);
            GL.EnableClientState(ArrayCap.ColorArray);
 
            // define pointers
            GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
            GL.VertexPointer(3, VertexPointerType.Float, Vertex.Stride, new IntPtr(0));
            GL.NormalPointer(NormalPointerType.Float, Vertex.Stride, new IntPtr(0));
            //GL.TexCoordPointer(2, VertexPointerType.Float, Vertex.Stride, new IntPtr(2 * Vector3.SizeInBytes));
            GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(int), IntPtr.Zero);
 
            GL.DrawArrays(PrimitiveType.Triangles, 0, data.Length);
 
            // disable client state
            GL.DisableClientState(ArrayCap.VertexArray);
            GL.DisableClientState(ArrayCap.NormalArray);
            GL.DisableClientState(ArrayCap.ColorArray);

Do i need to change anything in VBO mode to center the model? Why its different from immediate mode and VBO?

I attached the screenshot for reference. Please let me know where i need to make the changes.

Inline Images
VBO mode
Immediate mode

Comments

Comment viewing options

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

There are one more issue with VBO mode, mesh is flat comparing to immediate mode. Also, there are some shades when i rotate into left side.

Any suggestions?

the Fiddler's picture

The issue is caused by these lines:

            GL.VertexPointer(3, VertexPointerType.Float, Vertex.Stride, new IntPtr(0));
            GL.NormalPointer(NormalPointerType.Float, Vertex.Stride, new IntPtr(0));
            GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(int), IntPtr.Zero);

The last parameter is should be the offset of the relevant attribute into your vertex structure. For example:

struct Vertex
{
    public Vector3 Position;
    public Vector3 Normal;
    public Vector2 Color;
}

would need the following offsets:

            GL.VertexPointer(3, VertexPointerType.Float, Vertex.Stride, new IntPtr(0));
            GL.NormalPointer(NormalPointerType.Float, Vertex.Stride, new IntPtr(12));
            GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(int), new IntPtr(24));
winterhell's picture

If all vertex attributes are in the "vbo" variable, then you should put the offset for each attribute, and not IntPtr(0)

 GL.VertexPointer(3, VertexPointerType.Float, Vertex.Stride,0);
 GL.NormalPointer(NormalPointerType.Float, Vertex.Stride, Vector3.SizeInBytes);
 GL.ColorPointer(4, ColorPointerType.UnsignedByte, Vertex.Stride, Vector3.SizeInBytes + Vector3.SizeInBytes);

This assumes the vertex position is the first 3 floats, the normals are the next 3 floats, and finally the color starts after 6 floats/24bytes.
Make to pass the correct stride size as well.
As a rule of the thumb try to render it first with only vertex positions and then gradually add the code for the rest.

darkprinze's picture

I changed the offsets as per your suggestion, and i still get the same problem. I don't understand why mesh looks like flat (even though its not flat, it does look like that). I mean vertex position is same between immediate mode, and bounding box is also same right?

This is my vertex structure

 struct Vertex
    {
        public Vector3 Position, Normal;
        public Vector2 TexCoord;
        public int[] ColorArray;
        public static readonly int Stride = Marshal.SizeOf(default(Vertex));
    }

This is how i add color to array

data[j].ColorArray = new int[] { ColorToRgba32(System.Drawing.Color.LightGray) };
 
// methos to get argb value
public static int ColorToRgba32(System.Drawing.Color c)
        {
            return (int)((c.A << 24) | (c.B << 16) | (c.G << 8) | c.R);
        }

My array data looks like
data[0]:
Normal -0.0278551, -0.01331507, 0.9995233
Position 7.97872, 4.825144, 1.058551
ColorArray -2894893

data[1]:
Normal -0.0278551, -0.01331507, 0.9995233
Position 7.819146, 4.819074, 1.054023
ColorArray -2894893

data[2]:
Normal -0.0278551, -0.01331507, 0.9995233
Position 7.819146, 4.729444, 1.052829
ColorArray -2894893

xenapior's picture

Try GL.*Pointer(*, IntPtr(n)) instead of GL.*Pointer(*,new IntPtr(n)) .
Also, check the struct alignment of the vbo data array.

winterhell's picture

In your data array the normals are first, and the position is after that, so that should be reflected in the GL.VertexPointer and GL.NormalPointer

darkprinze's picture

Thanks for your suggestions. Fixed the issue.