C# OpenTK GL.drawerElements导致GL\u无效\u操作错误

C# OpenTK GL.drawerElements导致GL\u无效\u操作错误,c#,opengl,opengl-3,opentk,C#,Opengl,Opengl 3,Opentk,正如标题中所述,我从GLDrawerElements中获得了一个GL_INVALID_操作错误,然而,这只发生在GL 3.1以上的GL上下文中,在GL 3.1及以下的上下文中,它正确呈现,没有任何问题。我的模型是这样加载的: public IModel LoadData( Shape a_Shape ) { int VertexStride = BlittableValueType<Vertex>.Stride; int IndexStride = s

正如标题中所述,我从GLDrawerElements中获得了一个GL_INVALID_操作错误,然而,这只发生在GL 3.1以上的GL上下文中,在GL 3.1及以下的上下文中,它正确呈现,没有任何问题。我的模型是这样加载的:

public IModel LoadData( Shape a_Shape ) {
        int VertexStride = BlittableValueType<Vertex>.Stride;
        int IndexStride = sizeof ( uint );

        m_Backing = a_Shape;

        m_GLDataBuffer = GL.GenBuffer( );
        GL.BindBuffer( BufferTarget.ArrayBuffer, m_GLDataBuffer );
        GL.BufferData( BufferTarget.ArrayBuffer, ( IntPtr ) ( m_Backing.Vertices.Count * VertexStride ), m_Backing.Vertices.ToArray( ), BufferUsageHint.StaticDraw );

        m_GLIndexBuffer = GL.GenBuffer( );
        GL.BindBuffer( BufferTarget.ElementArrayBuffer, m_GLIndexBuffer );
        GL.BufferData( BufferTarget.ElementArrayBuffer, ( IntPtr ) ( m_Backing.Indices.Count * IndexStride ), m_Backing.Indices.ToArray( ), BufferUsageHint.StaticDraw );

        GL.EnableVertexAttribArray( 0 );
        GL.EnableVertexAttribArray( 1 );
        GL.EnableVertexAttribArray( 2 );
        GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, VertexStride, 0 );
        GL.VertexAttribPointer( 1, 3, VertexAttribPointerType.Float, false, VertexStride, ( sizeof ( float ) * 3 ) );
        GL.VertexAttribPointer( 2, 2, VertexAttribPointerType.Float, false, VertexStride, ( sizeof ( float ) * 6 ) );
        GL.DisableVertexAttribArray( 2 );
        GL.DisableVertexAttribArray( 1 );
        GL.DisableVertexAttribArray( 0 );

        GL.BindBuffer( BufferTarget.ArrayBuffer, 0 );
        GL.BindBuffer( BufferTarget.ElementArrayBuffer, 0 );
        return this;
    }
正如我所说,在我尝试使用3.1版以上的GL上下文之前,这一切都很好。我真的很困惑,它不能在3.1以上工作。我查看了它,在OpenGL参考上说:

如果非零缓冲区对象名称绑定到启用的数组或元素数组,并且缓冲区对象的数据存储当前已映射,则会生成GL_INVALID_操作

不过,我不太明白这意味着什么。所以我想我的问题是:是什么导致GLD元素只能在特定的环境下工作,我该如何着手解决它?或者这是我的代码中我没有看到的问题

任何帮助都将不胜感激,经过大约5个小时的努力,我发现是时候寻求帮助了

更新

因此,我将代码修改为以下内容:

    public IModel LoadData( Shape a_Shape ) {
        m_Backing = a_Shape;

        Single[] Positions = new Single[a_Shape.Vertices.Count * 3];
        Single[] Normals = new Single[a_Shape.Vertices.Count * 3];
        Single[] TexCoords = new Single[a_Shape.Vertices.Count * 2];

        for ( int i = 0; i < Positions.Length; i += 3 ) {
            Positions[i + 0] = a_Shape.Vertices[i / 3].Position.X;
            Positions[i + 1] = a_Shape.Vertices[i / 3].Position.Y;
            Positions[i + 2] = a_Shape.Vertices[i / 3].Position.Z;

            Normals[i + 0] = a_Shape.Vertices[i / 3].Normal.X;
            Normals[i + 1] = a_Shape.Vertices[i / 3].Normal.Y;
            Normals[i + 2] = a_Shape.Vertices[i / 3].Normal.Z;
        }

        for ( int i = 0; i < TexCoords.Length; i += 2 ) {
            TexCoords[i + 0] = a_Shape.Vertices[i / 2].TexCoord.X;
            TexCoords[i + 1] = a_Shape.Vertices[i / 2].TexCoord.Y;
        }

        m_GLVertexArray = GL.GenVertexArray( );
        GL.BindVertexArray( m_GLVertexArray );
        m_GLIndexBuffer = GL.GenBuffer( );
        GL.GenBuffers( 3, m_GLDataBuffers );
        GL.EnableVertexAttribArray( 0 );
        GL.EnableVertexAttribArray( 1 );
        GL.EnableVertexAttribArray( 2 );

        GL.BindBuffer( BufferTarget.ElementArrayBuffer, m_GLIndexBuffer );
        GL.BufferData( BufferTarget.ElementArrayBuffer, ( IntPtr ) ( sizeof ( uint ) * a_Shape.Indices.Count ), a_Shape.Indices.ToArray( ), BufferUsageHint.StaticDraw );

        GL.BindBuffer( BufferTarget.ArrayBuffer, m_GLDataBuffers[0] ); // Bind the Position Buffer
        GL.BufferData( BufferTarget.ArrayBuffer, ( IntPtr ) ( sizeof ( Single ) * Positions.Length ), Positions, BufferUsageHint.StaticDraw );
        GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0 );

        GL.BindBuffer( BufferTarget.ArrayBuffer, m_GLDataBuffers[1] ); // Bind the Normal Buffer
        GL.BufferData( BufferTarget.ArrayBuffer, ( IntPtr ) ( sizeof ( Single ) * Normals.Length ), Normals, BufferUsageHint.StaticDraw );
        GL.VertexAttribPointer( 1, 3, VertexAttribPointerType.Float, false, 0, 0 );

        GL.BindBuffer( BufferTarget.ArrayBuffer, m_GLDataBuffers[2] ); // Bind the TexCoord Buffer
        GL.BufferData( BufferTarget.ArrayBuffer, ( IntPtr ) ( sizeof ( Single ) * TexCoords.Length ), TexCoords, BufferUsageHint.StaticDraw );
        GL.VertexAttribPointer( 2, 2, VertexAttribPointerType.Float, false, 0, 0 );

        GL.BindBuffer( BufferTarget.ArrayBuffer, 0 );
        GL.BindBuffer( BufferTarget.ElementArrayBuffer, 0 );
        GL.BindVertexArray( 0 );
        return this;
    }
对于这幅画,我可以从雷托的评论中找到答案。我不再得到任何GL错误,但现在没有任何渲染。我再次看不出问题在哪里

编辑
修复了未正确地将顶点转换为位置、法线和TexCoord数组的问题。

我的原始问题的解决方案是使用顶点数组,因为OpenGL 3.1 Core到OpenGL 3.2 Core的不推荐使用,尝试在没有渲染的情况下渲染会抛出GL_无效_操作错误。后来我遇到了另一个问题,没有任何渲染,这是我的一个简单错误,没有重新绑定GL_元素_数组_缓冲区。主柱中的LoadData方法场景工作正常,最终绘制方法如下:

    void IModel.Draw( ) {
        GL.BindVertexArray( m_GLVertexArray );
        GL.BindBuffer( BufferTarget.ElementArrayBuffer, m_GLIndexBuffer ); //Rebinding the GL_ELEMENT_ARRAY_BUFFER solved the second issue.
        GL.DrawElements( PrimitiveType.Triangles, m_Backing.Indices.Count, DrawElementsType.UnsignedInt, 0 );
        GL.BindBuffer( BufferTarget.ElementArrayBuffer, 0 );
        GL.BindVertexArray( 0 );
    }
编辑

经过进一步讨论,我了解到,在解除绑定VAO之前,通过解除绑定
GL\u元素\u数组\u缓冲区(此处称为IBO),VAO会引用ID为0的IBO,而不是我希望它引用的IBO。下面是我正在使用的最终代码

    public IModel LoadData( Shape a_Shape ) {
        m_Backing = a_Shape;

        Single[] Positions = new Single[a_Shape.Vertices.Count * 3];
        Single[] Normals = new Single[a_Shape.Vertices.Count * 3];
        Single[] TexCoords = new Single[a_Shape.Vertices.Count * 2];

        for ( int i = 0; i < Positions.Length; i += 3 ) {
            Positions[i + 0] = a_Shape.Vertices[i / 3].Position.X;
            Positions[i + 1] = a_Shape.Vertices[i / 3].Position.Y;
            Positions[i + 2] = a_Shape.Vertices[i / 3].Position.Z;

            Normals[i + 0] = a_Shape.Vertices[i / 3].Normal.X;
            Normals[i + 1] = a_Shape.Vertices[i / 3].Normal.Y;
            Normals[i + 2] = a_Shape.Vertices[i / 3].Normal.Z;
        }

        for ( int i = 0; i < TexCoords.Length; i += 2 ) {
            TexCoords[i + 0] = a_Shape.Vertices[i / 2].TexCoord.X;
            TexCoords[i + 1] = a_Shape.Vertices[i / 2].TexCoord.Y;
        }

        m_GLVertexArray = GL.GenVertexArray( );
        GL.BindVertexArray( m_GLVertexArray );
        m_GLIndexBuffer = GL.GenBuffer( );
        GL.GenBuffers( 3, m_GLDataBuffers );

        GL.BindBuffer( BufferTarget.ElementArrayBuffer, m_GLIndexBuffer );
        GL.BufferData( BufferTarget.ElementArrayBuffer, ( IntPtr ) ( sizeof ( uint ) * a_Shape.Indices.Count ), a_Shape.Indices.ToArray( ), BufferUsageHint.StaticDraw );

        GL.BindBuffer( BufferTarget.ArrayBuffer, m_GLDataBuffers[0] ); // Bind the Position Buffer
        GL.BufferData( BufferTarget.ArrayBuffer, ( IntPtr ) ( sizeof ( Single ) * Positions.Length ), Positions, BufferUsageHint.StaticDraw );
        GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0 );
        GL.EnableVertexAttribArray( 0 );

        GL.BindBuffer( BufferTarget.ArrayBuffer, m_GLDataBuffers[1] ); // Bind the Normal Buffer
        GL.BufferData( BufferTarget.ArrayBuffer, ( IntPtr ) ( sizeof ( Single ) * Normals.Length ), Normals, BufferUsageHint.StaticDraw );
        GL.VertexAttribPointer( 1, 3, VertexAttribPointerType.Float, false, 0, 0 );
        GL.EnableVertexAttribArray( 1 );

        GL.BindBuffer( BufferTarget.ArrayBuffer, m_GLDataBuffers[2] ); // Bind the TexCoord Buffer
        GL.BufferData( BufferTarget.ArrayBuffer, ( IntPtr ) ( sizeof ( Single ) * TexCoords.Length ), TexCoords, BufferUsageHint.StaticDraw );
        GL.VertexAttribPointer( 2, 2, VertexAttribPointerType.Float, false, 0, 0 );
        GL.EnableVertexAttribArray( 2 );

        GL.BindBuffer( BufferTarget.ArrayBuffer, 0 );
        GL.BindVertexArray( 0 );
        GL.BindBuffer( BufferTarget.ElementArrayBuffer, 0 );
        return this;
    }

您可能会获得3.1以上版本的核心配置文件上下文,并且您的代码与核心配置文件不兼容。请参见示例:.@RetoKoradi我已经使用顶点数组更新了代码,但是现在根本没有渲染。我已经用我当前的代码更新了我的主要帖子。我刚刚意识到我实际上没有正确地将数据存储在数组中。我将编辑我的主要帖子以修复此问题。如果支持,您可以请求一个兼容性配置文件。我看不到使用OpenTK可以做到这一点的方法,我会继续查找,但这不是我看到的内容。
GL\u元素\u数组\u缓冲区
绑定是VAO状态的一部分。因此,如果在设置VAO时绑定它,当VAO被绑定时,就不必在
Draw()
方法中再次绑定它。这就是我所假设的,也是为什么我首先在Draw中删除了重新绑定它的调用,因为正在生成
GL\u元素\u数组\u buffer
的缓冲区,生成并绑定VAO后绑定并填充,但即使如此,我仍然需要重新绑定它。除非我被你的话弄糊涂了,那应该行得通的。在最初发布的代码中,还调用了解除绑定
GL\u元素\u数组\u缓冲区的操作。当然,您必须删除它,否则存储在VAO状态中的绑定将再次重置。我现在明白这是有道理的,出于某种原因,我认为我需要解除绑定,但现在我想,下次加载模型时,它将绑定一个新的VAO和IBO,因此首先解除绑定没有任何意义。
    void IModel.Draw( ) {
        GL.BindVertexArray( m_GLVertexArray );
        GL.BindBuffer( BufferTarget.ElementArrayBuffer, m_GLIndexBuffer ); //Rebinding the GL_ELEMENT_ARRAY_BUFFER solved the second issue.
        GL.DrawElements( PrimitiveType.Triangles, m_Backing.Indices.Count, DrawElementsType.UnsignedInt, 0 );
        GL.BindBuffer( BufferTarget.ElementArrayBuffer, 0 );
        GL.BindVertexArray( 0 );
    }
    public IModel LoadData( Shape a_Shape ) {
        m_Backing = a_Shape;

        Single[] Positions = new Single[a_Shape.Vertices.Count * 3];
        Single[] Normals = new Single[a_Shape.Vertices.Count * 3];
        Single[] TexCoords = new Single[a_Shape.Vertices.Count * 2];

        for ( int i = 0; i < Positions.Length; i += 3 ) {
            Positions[i + 0] = a_Shape.Vertices[i / 3].Position.X;
            Positions[i + 1] = a_Shape.Vertices[i / 3].Position.Y;
            Positions[i + 2] = a_Shape.Vertices[i / 3].Position.Z;

            Normals[i + 0] = a_Shape.Vertices[i / 3].Normal.X;
            Normals[i + 1] = a_Shape.Vertices[i / 3].Normal.Y;
            Normals[i + 2] = a_Shape.Vertices[i / 3].Normal.Z;
        }

        for ( int i = 0; i < TexCoords.Length; i += 2 ) {
            TexCoords[i + 0] = a_Shape.Vertices[i / 2].TexCoord.X;
            TexCoords[i + 1] = a_Shape.Vertices[i / 2].TexCoord.Y;
        }

        m_GLVertexArray = GL.GenVertexArray( );
        GL.BindVertexArray( m_GLVertexArray );
        m_GLIndexBuffer = GL.GenBuffer( );
        GL.GenBuffers( 3, m_GLDataBuffers );

        GL.BindBuffer( BufferTarget.ElementArrayBuffer, m_GLIndexBuffer );
        GL.BufferData( BufferTarget.ElementArrayBuffer, ( IntPtr ) ( sizeof ( uint ) * a_Shape.Indices.Count ), a_Shape.Indices.ToArray( ), BufferUsageHint.StaticDraw );

        GL.BindBuffer( BufferTarget.ArrayBuffer, m_GLDataBuffers[0] ); // Bind the Position Buffer
        GL.BufferData( BufferTarget.ArrayBuffer, ( IntPtr ) ( sizeof ( Single ) * Positions.Length ), Positions, BufferUsageHint.StaticDraw );
        GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0 );
        GL.EnableVertexAttribArray( 0 );

        GL.BindBuffer( BufferTarget.ArrayBuffer, m_GLDataBuffers[1] ); // Bind the Normal Buffer
        GL.BufferData( BufferTarget.ArrayBuffer, ( IntPtr ) ( sizeof ( Single ) * Normals.Length ), Normals, BufferUsageHint.StaticDraw );
        GL.VertexAttribPointer( 1, 3, VertexAttribPointerType.Float, false, 0, 0 );
        GL.EnableVertexAttribArray( 1 );

        GL.BindBuffer( BufferTarget.ArrayBuffer, m_GLDataBuffers[2] ); // Bind the TexCoord Buffer
        GL.BufferData( BufferTarget.ArrayBuffer, ( IntPtr ) ( sizeof ( Single ) * TexCoords.Length ), TexCoords, BufferUsageHint.StaticDraw );
        GL.VertexAttribPointer( 2, 2, VertexAttribPointerType.Float, false, 0, 0 );
        GL.EnableVertexAttribArray( 2 );

        GL.BindBuffer( BufferTarget.ArrayBuffer, 0 );
        GL.BindVertexArray( 0 );
        GL.BindBuffer( BufferTarget.ElementArrayBuffer, 0 );
        return this;
    }
void IModel.Draw( ) {
    GL.BindVertexArray( m_GLVertexArray );
    GL.DrawElements( PrimitiveType.Triangles, m_Backing.Indices.Count, DrawElementsType.UnsignedInt, 0 );
    GL.BindVertexArray( 0 );
}