时间:2019-03-08 标签:c#opentkAccessViolationException

c# opentk AccessViolationException

我目前是一名学生,正在编写游戏。为此,我在开始时将纹理加载到程序中,并在需要时让这些渲染。
到目前为止它确实有效,但有时我会得到 AccessViolationException。我已经尝试了很多我在互联网上找到的方法,但没有任何效果。这个错误真的很令人沮丧,因为它不定期发生。有时它会在 20 秒后崩溃,有时它会持续 8 分钟。
将 frames_per_second 限制为 20 有帮助,我注意到它会崩溃,当有很多对象要渲染时,它不会经常崩溃,但它仍然会崩溃。

这是我在开头加载纹理的代码:

        Dictionary<string, Texture> ddc = new Dictionary<string, Texture>();
        DirectoryInfo img_dir = new DirectoryInfo("./Resources/drawable/");
        foreach(FileInfo file in img_dir.GetFiles())
        {
            string name = file.Name.Substring(0, file.Name.Length - 4);
            if (name.StartsWith("spr_"))
            {
                Bitmap bmp = new Bitmap(file.FullName);
                int texture = GL.GenTexture();

                BitmapData bmp_data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                GL.BindTexture(TextureTarget.Texture2D, texture);

                        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp.Width, bmp.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0);
                bmp.UnlockBits(bmp_data);

                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Clamp);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Clamp);


                ddc.Add(name.Substring(4), new Texture()
                {
                    TextureID = texture,
                    Rows = (bmp.Height/64),
                    Columns = (bmp.Width/64)
                });
            }
        }
        return ddc;

它将带有名称的 ID 保存在 ddc 中,因此我可以使用它在游戏中获得正确的纹理。 这是渲染 Class,游戏总是在必须渲染某些东西时抛出它:

public void init()
    {
        //starts at the beginning of the Gamestart

        textures = resourceHandler.loadTextures();

        textures["font"].Rows = 16;
        textures["font"].Columns = 16;

        GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        GL.MatrixMode(MatrixMode.Projection);
        GL.LoadIdentity();
        GL.Ortho(0.0f, Game.SCREEN_WIDTH, 0.0f, Game.SCREEN_HEIGHT, -1.0f, 1.0f);
        GL.MatrixMode(MatrixMode.Modelview);

        GL.Enable(EnableCap.Texture2D);
        GL.Enable(EnableCap.Blend);
        GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

        GL.ActiveTexture(TextureUnit.Texture0);
    }

    public void batchDraw(int x, int y, int w, int h, float tx, float ty, float tw, float th)
    {
        GL.VertexPointer(2, VertexPointerType.Float, 0, new float[] { x, y, x + w, y, x, y + h, x + w, y + h });
        GL.EnableClientState(ArrayCap.VertexArray);
        GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, new float[] { tx, ty + th, tx + tw, ty + th, tx , ty, tx + tw, ty });
        GL.EnableClientState(ArrayCap.TextureCoordArray);

        //Sometimes Error at DrawArrays: AccessViolationException
        GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);

        GL.DisableClientState(ArrayCap.VertexArray);
        GL.DisableClientState(ArrayCap.TextureCoordArray);
    }

希望有人能帮助我

我不太熟悉 C# 及其作用域规则,但我的第一个预感是您为 VertexPointerTexCoordPointer 创建的原位数组(new float[]{…} ) 在到达 DrawArrays 的调用之前被释放。 …Pointer 函数不会创建您传递给它们的数据的内部副本;它们存储指向您传递给它们的某个内存区域的指针,并且该指针将仅在 Draw… 调用时被取消引用。

如果是这种情况,您必须将数组保留在范围内,直到绘图发生:

public void batchDraw(int x, int y, int w, int h, float tx, float ty, float tw, float th)
{
    float[] vpos = new float[] { x, y, x + w, y, x, y + h, x + w, y + h };
    float[] vtxc = new float[] { tx, ty + th, tx + tw, ty + th, tx , ty, tx + tw, ty };
    GL.VertexPointer(2, VertexPointerType.Float, 0, vpos);
    GL.EnableClientState(ArrayCap.VertexArray);
    GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, vtxc);
    GL.EnableClientState(ArrayCap.TextureCoordArray);

    //Sometimes Error at DrawArrays: AccessViolationException
    GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);

    GL.DisableClientState(ArrayCap.VertexArray);
    GL.DisableClientState(ArrayCap.TextureCoordArray);
}

请注意,您在那里所做的所有事情都使用旧的固定功能管道并分配需要的小数组。这是直接通过即时模式调用(glTexCoord、glVertex)可能会表现更好的情况之一。

当然,您一开始就不应该使用那种老式的 OpenGL。