c#opentk AccessViolationException
我目前是一名学生,正在编写一个游戏。为此,我在开始时将纹理加载到程序中,并在需要时进行渲染。c#opentk AccessViolationException,c#,opengl,textures,access-violation,opentk,C#,Opengl,Textures,Access Violation,Opentk,我目前是一名学生,正在编写一个游戏。为此,我在开始时将纹理加载到程序中,并在需要时进行渲染。 到目前为止它确实有效,但有时我会遇到AccessViolationException。我已经尝试了很多我在互联网上找到的东西,但是没有任何效果。这个错误确实令人沮丧,因为它发生得不规则。有时在20秒后崩溃,有时持续8分钟。 将每秒帧数限制为20有帮助,我注意到它会崩溃,当有很多对象要渲染时,所以它不会经常崩溃,但它仍然会崩溃 以下是我在开始时加载纹理的代码: Dictionary<
到目前为止它确实有效,但有时我会遇到
AccessViolationException
。我已经尝试了很多我在互联网上找到的东西,但是没有任何效果。这个错误确实令人沮丧,因为它发生得不规则。有时在20秒后崩溃,有时持续8分钟。将每秒帧数限制为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;
我希望有人能帮助我我对C#及其作用域规则不太熟悉,但我的第一个预感是,在调用
DrawArrays
之前,您为VertexInter
和TexCoordPointer
(new float[]{…}
)创建的原位数组将被释放。…指针
函数不会创建传递给它们的数据的内部副本;它们存储指向您传递给它们的某个内存区域的指针,该指针将仅在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。几乎正确。这会增加工作执行的可能性,但并不健壮:垃圾收集器可以自由移动托管内存,从而在绘图时导致无效指针。解决方案是固定受管阵列@安迪
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);
}