Исключение OutOfMemory при рисовании куба

у меня есть класс, который тянет и поворачивает куб. каждый раз, когда я поворачиваю куб, я перезагружаю буфер с новыми значениями для куба.

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

затем назовите Куб. Нарисуйте метод в Игре. Потянуть

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

мог кто-то объяснять, почему это происходит и что я могу сделать для решения его.

7
задан harryovers 29 July 2010 в 15:56
поделиться

2 ответа

Буферы вершин - это неуправляемые ресурсы. Сборщик мусора не знает , что они за кулисами используют целую кучу неуправляемой памяти (и ресурсов графического процессора). Все, о чем он знает, - это крошечный кусочек управляемой памяти, который использует каждый из них.

Я больше говорю о неуправляемых ресурсах в XNA в моем ответе на этот вопрос .

Вы можете вызвать Dispose () для каждого VertexBuffer перед утечкой его (но после завершения рисования, поскольку он все еще будет использоваться!), Чтобы освободить неуправляемые ресурсы.Это позволит избежать ошибки нехватки памяти, но все равно будет работать очень медленно!

На самом деле вам следует создать минимально необходимый буфер вершин только один раз . Идеальное место для этого - в вашей функции LoadContent (а затем Dispose () в вашей функции UnloadContent ). Если у вас есть целая группа кубов, все, что вам нужно, - это единственный буфер вершин, описывающий куб, который вы повторно используете каждый раз, когда рисуете куб.

Очевидно, вы не хотите рисовать все кубики в одном месте. Для этого и предназначена Мировая матрица. Каждый раз, когда вы рисуете куб, устанавливайте BasicEffect.World в свою матрицу преобразования для этого куба и вызывайте Apply () .

(То, как вы устанавливаете WorldViewProj напрямую, тоже нормально. Но использовать хороший API, ну, лучше.)

Если вам нужно вращение, используйте Matrix.CreateFromYawPitchRoll (рыскание, тангаж, крен) для создания матрицы преобразования.

Подробнее об этом: ваша проблема похожа на , на другой вопрос, на который я ответил .

(Обратите внимание, что если сами вершины действительно изменяют каждый кадр, вы должны использовать DrawUserPrimitives . Но обратите внимание, что это все равно значительно медленнее, чем разрешение вершинному шейдеру на GPU обрабатывать любые преобразования.)

8
ответ дан 7 December 2019 в 05:16
поделиться

Похоже, что вы создаете новый вершинный буфер каждый кадр и не позволяете старому буферу выпасть из области видимости для сборки мусора. Фактически вы делаете это для каждого из ваших кубиков.

Лучшим подходом было бы просто обновлять значения вершин каждый кадр, а еще лучше обновлять трансформацию куба каждый кадр.

0
ответ дан 7 December 2019 в 05:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: