麻烦纹理VBO

时间:2014-09-20 19:30:44

标签: c# opengl vbo texture-mapping opentk

似乎我在游戏中对VBO进行纹理处理时遇到了一些麻烦。 VBO本身似乎渲染得很好,我甚至可以相应地切换面。然而,当我尝试添加纹理时,一切看起来都是倾斜的,一些纹理甚至在错误的面上。当我使用VAO时,一切都运转良好,所以我目前不知道为什么纹理突然不起作用。

这是一张图片:

enter image description here

以下是相关数据:

private static uint frontFaceHandle;
        private static uint backFaceHandle;
        private static uint leftFaceHandle;
        private static uint rightFaceHandle;
        private static uint topFaceHandle;
        private static uint bottomFaceHandle;


        private static uint indexBufferId;
        private static uint colorBufferId;
        private static uint texCoordBufferId;

        private static float[] textureCoordData = {
            0, 1,
            1, 1,
            1, 0,
            0, 0,
        };

        private static ushort[] indices = {
            0, 1, 3,
            0, 3, 2
        };

        private static float[] colorData = {
            1.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 0.0f,
        };

        private static float[] frontFaceVert = {
            -1.0f, -1.0f, -1.0f,
            -1.0f, -1.0f, 1.0f,
            -1.0f, 1.0f, -1.0f,
            -1.0f, 1.0f, 1.0f
        };

        private static float[] backFaceVert = {
            1.0f, -1.0f, 1.0f,
            1.0f, -1.0f, -1.0f,
            1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, -1.0f,
        };

        private static float[] leftFaceVert = {
            1.0f, -1.0f, -1.0f,
            -1.0f, -1.0f, -1.0f,
            1.0f, 1.0f, -1.0f,
            -1.0f, 1.0f, -1.0f,
        };

        private static float[] rightFaceVert = {
            -1.0f, -1.0f, 1.0f,
            1.0f, -1.0f, 1.0f,
            -1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f,
        };

        private static float[] topFaceVert = {
            -1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f,
            -1.0f, 1.0f, -1.0f,
            1.0f, 1.0f, -1.0f,
        };

        private static float[] bottomFaceVert = {
            -1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,
            -1.0f, -1.0f, 1.0f,
            1.0f, -1.0f, 1.0f,
        };

我上传数据的方式:

static Voxel() {
            /**
             * Front Face
             */
            GL.GenBuffers( 1 , out frontFaceHandle );
            GL.BindBuffer( BufferTarget.ArrayBuffer , frontFaceHandle );
            GL.BufferData(
                BufferTarget.ArrayBuffer ,
                ( IntPtr )( frontFaceVert.Length * sizeof( float ) ) ,
                frontFaceVert ,
                BufferUsageHint.StaticDraw );
            /**
             * Back Face
             */
            GL.GenBuffers( 1 , out backFaceHandle );
            GL.BindBuffer( BufferTarget.ArrayBuffer , backFaceHandle );
            GL.BufferData(
                BufferTarget.ArrayBuffer ,
                ( IntPtr )( backFaceVert.Length * sizeof( float ) ) ,
                backFaceVert ,
                BufferUsageHint.StaticDraw );
            /**
             * Left Face
             */
            GL.GenBuffers( 1 , out leftFaceHandle );
            GL.BindBuffer( BufferTarget.ArrayBuffer , leftFaceHandle );
            GL.BufferData(
                BufferTarget.ArrayBuffer ,
                ( IntPtr )( leftFaceVert.Length * sizeof( float ) ) ,
                leftFaceVert ,
                BufferUsageHint.StaticDraw );
            /**
             * Right Face
             */
            GL.GenBuffers( 1 , out rightFaceHandle );
            GL.BindBuffer( BufferTarget.ArrayBuffer , rightFaceHandle );
            GL.BufferData(
                BufferTarget.ArrayBuffer ,
                ( IntPtr )( rightFaceVert.Length * sizeof( float ) ) ,
                rightFaceVert ,
                BufferUsageHint.StaticDraw );
            /**
             * Top Face
             */
            GL.GenBuffers( 1 , out topFaceHandle );
            GL.BindBuffer( BufferTarget.ArrayBuffer , topFaceHandle );
            GL.BufferData(
                BufferTarget.ArrayBuffer ,
                ( IntPtr )( topFaceVert.Length * sizeof( float ) ) ,
                topFaceVert ,
                BufferUsageHint.StaticDraw );
            /**
             * Bottom Face
             */
            GL.GenBuffers( 1 , out bottomFaceHandle );
            GL.BindBuffer( BufferTarget.ArrayBuffer , bottomFaceHandle );
            GL.BufferData(
                BufferTarget.ArrayBuffer ,
                ( IntPtr )( bottomFaceVert.Length * sizeof( float ) ) ,
                bottomFaceVert ,
                BufferUsageHint.StaticDraw );
            /**
             * Texture Buffer
             */
            GL.GenBuffers( 1 , out texCoordBufferId );
            GL.BindBuffer( BufferTarget.ArrayBuffer , texCoordBufferId );
            GL.BufferData( BufferTarget.ArrayBuffer , ( IntPtr )( textureCoordData.Length * sizeof( float ) ) , textureCoordData , BufferUsageHint.StaticDraw );

            /**
             * Index Buffer
             */
            GL.GenBuffers( 1 , out indexBufferId );
            GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
            GL.BufferData(
                BufferTarget.ElementArrayBuffer ,
                ( IntPtr )( indices.Length * sizeof( ushort ) ) ,
                indices ,
                BufferUsageHint.StaticDraw );
            /**
             * Color buffer (This Remains unused for now
             */
            GL.GenBuffers( 1 , out colorBufferId );
            GL.BindBuffer( BufferTarget.ArrayBuffer , colorBufferId );
            GL.BufferData(
                BufferTarget.ArrayBuffer ,
                ( IntPtr )colorData.Length ,
                colorData ,
                BufferUsageHint.StaticDraw );
        }

我绘制立方体的方式(每张脸都是单独的vbo):

public void Render( FirstPersonCameraWidget gameCamera ) {
            GL.Translate( Location.X , Location.Y , Location.Z );
            GL.Enable( EnableCap.Texture2D );
            GL.EnableClientState( ArrayCap.VertexArray );
            GL.EnableClientState( ArrayCap.TextureCoordArray );
            if( ShowFrontFace ) {

                GL.BindBuffer( BufferTarget.ArrayBuffer , frontFaceHandle );
                GL.BindBuffer( BufferTarget.TextureBuffer , texCoordBufferId );
                GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
                GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );
                GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
                GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.FrontFace.GetID() );
                GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );
            }
            if( ShowBackFace ) {
                GL.BindBuffer( BufferTarget.ArrayBuffer , backFaceHandle );
                GL.BindBuffer( BufferTarget.TextureBuffer , texCoordBufferId );
                GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
                GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );
                GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
                GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.BackFace.GetID() );
                GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );
            }
            if( ShowLeftFace ) {
                GL.BindBuffer( BufferTarget.ArrayBuffer , leftFaceHandle );
                GL.BindBuffer( BufferTarget.TextureBuffer , texCoordBufferId );
                GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
                GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );
                GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
                GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.LeftFace.GetID() );
                GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );
            }
            if( ShowRightFace ) {
                GL.BindBuffer( BufferTarget.ArrayBuffer , rightFaceHandle );
                GL.BindBuffer( BufferTarget.TextureBuffer , texCoordBufferId );
                GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
                GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );
                GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
                GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.RightFace.GetID() );
                GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );
            }
            if( ShowTopFace ) {
                GL.BindBuffer( BufferTarget.ArrayBuffer , topFaceHandle );
                GL.BindBuffer( BufferTarget.TextureBuffer , texCoordBufferId );
                GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
                GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );
                GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
                GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.TopFace.GetID() );
                GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );
            }
            if( ShowBottomFace ) {
                GL.BindBuffer( BufferTarget.ArrayBuffer , bottomFaceHandle );
                GL.BindBuffer( BufferTarget.TextureBuffer , texCoordBufferId );
                GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
                GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );
                GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
                GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.BottomFace.GetID() );
                GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );
            }
            GL.Translate( -Location.X , -Location.Y , -Location.Z );
        }

希望有人能发现我做错了什么。

更新:我已根据@Andom M. Coleman的建议修改了代码并且它工作正常,但多维数据集仍然略微倾斜。

enter image description here

1 个答案:

答案 0 :(得分:3)

您正在为纹理坐标数组和位置数组使用不同的VBO,对吗?这些东西没有离散的绑定位置,您的代码应该看起来像这样:

        if( ShowFrontFace ) {
            GL.BindBuffer( BufferTarget.ArrayBuffer , frontFaceHandle );
            GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );

            // ArrayBuffer!
            GL.BindBuffer( BufferTarget.ArrayBuffer , texCoordBufferId ); 
            GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );

            GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.FrontFace.GetID() );

            GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
            GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );

注意: BufferTarget.TextureBuffer实际上是对缓冲区对象(纹理缓冲区对象)的完全不同的使用。

对于顶点缓冲区,您始终将它们绑定到BufferTarget.ArrayBuffer,然后下一个gl___CoordPointer (...)调用将相对于当前绑定的任何内容。

在原始代码中,由于BufferTarget.ArrayBuffer仅被设置一次,因此纹理坐标指针实际上来自与顶点位置相同的数据集。这显然不是你想要的行为。


事实上,如果你想获得幻想,你可以将纹理指针的规格从分支中拉出来,因为它是不变的。每次绘制多维数据集时,只需执行以下 一次

            GL.BindBuffer     ( BufferTarget.ArrayBuffer , texCoordBufferId     ); 
            GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );