我有一个绘制和旋转立方体的类。每次我旋转立方体时,我都会用立方体的新值重新加载缓冲区。
public void LoadBuffer(GraphicsDevice graphicsDevice)
{
buffer = new VertexBuffer(graphicsDevice, VertexPositionNormalTexture.VertexDeclaration, triangles * 3, BufferUsage.None);
buffer.SetData<VertexPositionNormalTexture>(verts);
graphicsDevice.SetVertexBuffer(buffer);
}
public void Draw(GraphicsDevice graphicsDevice)
{
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, triangles);
}
然后在 Game.Draw 中调用 Cube.Draw 方法
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Target, Color.White, 1f, 0);
basicEffect.Parameters["WorldViewProj"].SetValue(world * view * projection);
EffectPass pass = basicEffect.CurrentTechnique.Passes[0];
if (pass != null)
{
pass.Apply();
cube1.LoadBuffer(GraphicsDevice);
cube1.Draw(GraphicsDevice);
cube2.LoadBuffer(GraphicsDevice);
cube2.Draw(GraphicsDevice);
cube3.LoadBuffer(GraphicsDevice);
cube3.Draw(GraphicsDevice);
}
base.Draw(gameTime);
}
大约几分钟后,我在线上收到了 OutOfMemory 异常:
buffer.SetData<VertexPositionNormalTexture>(verts);
有人可以解释为什么会发生这种情况以及我能做些什么来解决它。
最佳答案
顶点缓冲区是非托管资源。垃圾收集器不知道他们在幕后使用了一大堆非托管内存(和 GPU 资源)。它所知道的只是每个人使用的一小部分托管内存。
我在 my answer to this question 中更多地谈论 XNA 中的非托管资源。 .
您可以调用Dispose()
在每个 VertexBuffer
在你泄露它之前(但在绘制完成之后,因为它仍然会被使用!),释放非托管资源。这将避免内存不足错误,但仍然会很慢!
你真正应该做的是只创建一次最少的必要顶点缓冲区。执行此操作的理想地点是您的 LoadContent
函数(然后 Dispose()
它们在您的 UnloadContent
函数中)。如果你有一大堆立方体,你只需要一个描述立方体的顶点缓冲区,每次绘制立方体时都可以重复使用它。
显然你不想在同一个地方绘制所有的立方体。这就是 World 矩阵的用途。每次绘制立方体时,设置 BasicEffect.World
到该立方体的转换矩阵并调用 Apply()
.
(您直接设置 WorldViewProj
的方式也可以。但是使用 nice API 会更好。)
如果您想要旋转,请使用 Matrix.CreateFromYawPitchRoll(yaw, pitch, roll)
创建您的转换矩阵。
有关此的更多详细信息,您的问题类似于 another question I have answered .
(请注意,如果顶点本身确实改变了每一帧,您应该使用 DrawUserPrimitives
。但请注意,这仍然比让 GPU 上的顶点着色器处理任何变换要慢得多。)
关于.net - 绘制立方体时出现 OutOfMemory 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3364481/