我目前是一名学生,正在编写游戏。为此,我在开始时将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);
}
我希望有人可以帮助我
答案 0 :(得分:1)
我不熟悉C#及其范围规则,但我的第一个预感是你为TexCoordPointer
和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);
}
调用时才会取消引用该指针。
如果是这种情况,你必须将数组保持在范围内,直到绘图发生:
{
name: "John Doe",
email: "doe@example.com"
}
请注意,您在那里做的所有事情都使用旧的固定功能管道并分配quire小数组。这是直接通过立即模式调用(glTexCoord,glVertex)可能会表现更好的情况之一。
当然,你不应该首先使用那种旧式的OpenGL。