Home > Enterprise >  Opengl does not find texture coordinates VertexAttribPointer
Opengl does not find texture coordinates VertexAttribPointer

Time:10-10

I have probably a very simple question in OpenGL. I want to draw different shapes with textures on them. So I defined a vertex struct, which contains the positions of knots and additional information (normal vector, texture coordinates, reference to texture):

public struct Vertex
{
    public Vector3 position;
    public Vector3 normal;
    public Vector2 texCoord;
    public int texid;

    public static int SizeInBytes
    {
        get { return Vector3.SizeInBytes * 2   Vector2.SizeInBytes   sizeof(int); }
    }
    public Vertex(Vector3 position, Vector3 normal, Vector2 texCoord, int texid)
    {
        this.position = position;
        this.normal = normal;
        this.texCoord = texCoord;
        this.texid = texid;
    }
}

Then I create 2 vertex arrays (VA_TopBottom_WP and VA_Side_WP) with its vertex buffers (VB_TopBottom_WP and VB_Side_WP). Moreover, I create all textures.

internal void init()
    {

        // Create Buffer for top and bottom part
        GL.GenVertexArrays(1, out VA_TopBottom_WP);
        GL.BindVertexArray(VA_TopBottom_WP);
        VB_TopBottom_WP = GL.GenBuffer();

        // Create Buffer for side part
        GL.GenVertexArrays(1, out VA_Side_WP);
        GL.BindVertexArray(VA_Side_WP);
        VB_Side_WP = GL.GenBuffer();

        // Create textures 
        texes = new List<STL_Tools.Texture2D>();
        texes.Add(new STL_Tools.Texture2D());//Default texture
        for (int n = 0; n < session.pgm.Count(); n  )
        {
            texes.Add(new STL_Tools.Texture2D());
        }
        updateFrame();
        
        
    }

Then I update the buffer content:

public void updateFrame()
    {
        // Top and bottom buffer
        GL.BindVertexArray(VA_TopBottom_WP);
        GL.BindBuffer(BufferTarget.ArrayBuffer, VB_TopBottom_WP);
        
        //Fill vertex structure
        vertBuffer_TopBottom = poly.GetTopBottomMeshesVertex();
        GL.BufferData<Vertex>(BufferTarget.ArrayBuffer, (IntPtr)(Vertex.SizeInBytes * vertBuffer_TopBottom.Length), vertBuffer_TopBottom, BufferUsageHint.StaticDraw);
        GL.EnableVertexAttribArray(0);
        GL.VertexAttribPointer(0,3, VertexAttribPointerType.Float,false, Vertex.SizeInBytes, (IntPtr)0);//Position
        GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, (IntPtr)(Vector3.SizeInBytes*2));//Texture
        GL.VertexAttribPointer(2, 3, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, (IntPtr)(Vector3.SizeInBytes));//Normal

        // Side buffer
        GL.BindVertexArray(VA_Side_WP);
        GL.BindBuffer(BufferTarget.ArrayBuffer, VB_Side_WP);
        vertBuffer_Side = poly.GetSideVertex();//Fill vertices
        GL.BufferData<Vertex>(BufferTarget.ArrayBuffer, (IntPtr)(Vertex.SizeInBytes * vertBuffer_Side.Length), vertBuffer_Side, BufferUsageHint.StaticDraw);
        GL.EnableVertexAttribArray(0);
        GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, (IntPtr)0);//Position
        GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, (IntPtr)(Vector3.SizeInBytes * 2));//Texture
        GL.VertexAttribPointer(2, 3, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, (IntPtr)(Vector3.SizeInBytes));//Normal

        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
    }

The Vertex variables contain afterwards reasonable texture coordinates (Vector2 objects in the following). E. g.:

vertBuffer_Side = new Vertex[4]
{new Vertex(new Vector3(0,0,0),new Vector3(1,0,0),new Vector2(0,0),0),
 new Vertex(new Vector3(0,-80,0),new Vector3(1,0,0),new Vector2(1,0),0),
 new Vertex(new Vector3(0,-80,-10),new Vector3(1,0,0),new Vector2(1,1),0),
 new Vertex(new Vector3(0,0,-10),new Vector3(1,0,0),new Vector2(0,0),0)};

Then I draw everything with the following function:

public void renderFrame()
    {
        GL.PushMatrix();
        
        GL.EnableClientState(ArrayCap.VertexArray);
        GL.EnableClientState(ArrayCap.NormalArray);
        GL.EnableClientState(ArrayCap.TextureCoordArray);
        

        // Draw Side
        GL.BindVertexArray(VA_Side_WP);
        GL.Color3(Color.White);
        GL.Enable(EnableCap.Texture2D);
        for (int n = 0; n < (vertBuffer_Side.Length / 4); n  )
        {
            //GL.BindTexture(TextureTarget.Texture2D, 0);
            GL.BindTexture(TextureTarget.Texture2D, texes[vertBuffer_Side[n*4].texid].ID);
            GL.DrawArrays(PrimitiveType.Quads, n*4,4);
        }
        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
        GL.Disable(EnableCap.Texture2D);
        //Draw top and bottom
        GL.BindVertexArray(VA_TopBottom_WP);
        ...
        GL.PopMatrix();
    }

The geometry is drawn correctly. But the texture is not drawn correctly. It is drawn only with one color. It is the color of the far right pixel of the textures. Probably, the following function does not work correctly:

GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, (IntPtr)(Vector3.SizeInBytes * 2));//Texture

Where is my mistake?

CodePudding user response:

The client-side capabilities are states of the Vertex Array Object. Therefor you need to bind the VAO before setting the client-side capabilities. Also, you are not using a shader, but a shader program. Therefore, you must define the VertexPointer, NormalVector and TexCoordPointer instead of specifying generic arrays of vertex attributes. Note that it is possible to specify the vertex attribute 0 instead of the VertexPointer, but this is not possible for the normals and texture coordinates (also see What are the Attribute locations for fixed function pipeline in OpenGL 4.0 core profile?):

GL.VertexPointer(3, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, (IntPtr)0);//Position
GL.TexCoordPointer(2, VertexAttribPointerType.Float, false, Vertex.SizeInBytes, (IntPtr)(Vector3.SizeInBytes*2));//Texture
GL.NormalPointer(VertexAttribPointerType.Float, false, Vertex.SizeInBytes, (IntPtr)(Vector3.SizeInBytes));//Normal
GL.BindVertexArray(VA_Side_WP);
GL.EnableClientState(ArrayCap.VertexArray);
GL.EnableClientState(ArrayCap.NormalArray);
GL.EnableClientState(ArrayCap.TextureCoordArray);
  • Related