c#opentk AccessViolationException

时间:2017-11-30 09:56:02

标签: c# opengl textures access-violation opentk

我目前是一名学生,正在编写游戏。为此,我在开始时将Textures加载到程序中,并在需要时让这些渲染 到目前为止它确实有效,但有时我会得到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;

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

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);
    }

我希望有人可以帮助我

1 个答案:

答案 0 :(得分:1)

我不熟悉C#及其范围规则,但我的第一个预感是你为TexCoordPointernew 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); } 调用时才会取消引用该指针。

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

{
  name: "John Doe",
  email: "doe@example.com"
}

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

当然,你不应该首先使用那种旧式的OpenGL。