Z проблема с буфером путем смешивания 2D-спрайтов с 3D-моделью

Я должен создать 2d-меню над 3d-моделью, используя XNA. Прямо сейчас я создал spritebatch для 2D и 3d-модель. Но, как я заметил, и упоминалось в других местах, модель не отображается должным образом из-за проблемы с буфером Z. Согласно учебнику, я должен снова включить DepthBuffer в методе draw. Но, как-то, когда я использую:

GraphicsDevice.DepthStencilState.DepthBufferEnable = true;

код вызывает ошибку во время отладки, говоря:

не может изменить только для чтения DepthStencilState. Объекты состояния становятся доступными только для чтения при первой привязке к GraphicsDevice. Чтобы изменить значения свойств, создайте новый экземпляр DepthStencilState.

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

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

вот код рисования Для справки.

protected override void Draw(GameTime gameTime)
{
     GraphicsDevice.Clear(Color.CornflowerBlue);

     Matrix[] transforms = new Matrix[myModel.Bones.Count];
     myModel.CopyAbsoluteBoneTransformsTo(transforms);

     foreach (ModelMesh mesh in myModel.Meshes)
     {
         foreach (BasicEffect effect in mesh.Effects)
         {
             effect.EnableDefaultLighting();

             //effect.DirectionalLight0.Enabled = true;
             //effect.DirectionalLight0.DiffuseColor = Color.AntiqueWhite.ToVector3();
             //effect.DirectionalLight0.Direction = new Vector3(0, 0, 0);

             effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateRotationY(myModelRotation) * Matrix.CreateTranslation(myModelPosition);
             effect.View = Matrix.CreateLookAt(new Vector3(0, 0, 3000), Vector3.Zero, Vector3.Up);
             effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45f),
             GraphicsDevice.Viewport.AspectRatio, 1, 5000);
         }

         mesh.Draw();
    }

    spriteBatch.Begin();
    spriteBatch.Draw(myTexture, new Vector2(0, 0), Color.White);
    spriteBatch.End();

    DepthStencilState d = new DepthStencilState();
    d.DepthBufferEnable = true;
    GraphicsDevice.DepthStencilState = d;

    base.Draw(gameTime);
}

4 ответов


нельзя изменить объект DepthStencilState после его установки на устройстве. Вы должны создать один объект DepthStencilState для каждого уникального параметра глубины / трафарета, который вы хотите использовать. Оптимально, эти состояния должны быть созданы только один раз в вашей программе, а затем установлены на устройство, когда это необходимо.

для получения дополнительной информации см. состояние объектов в XNA Game Studio 4.0 Шон Харгривз.

дополнительные Подробности:

вы устанавливаете DepthBufferEnable в true, но не DepthBufferWriteEnable в true. Вместо того, чтобы пытаться установить эти свойства по отдельности, было бы лучше использовать предварительно построенные объекты DepthStencilState, предоставляемые платформой. Перед отрисовкой модели установите GraphicsDevice.DepthStencilState в DepthStencilState.По умолчанию. Это установит для свойств DepthBufferEnable и DepthBufferWriteEnable значение true.

Вам также нужно чтобы установить BlendState на устройстве в BlendState.Непрозрачный.

вам нужно установить эти рендерстаты, прежде чем рисовать модель, потому что SpriteBatch.Begin () автоматически изменяет renderstate на DepthStencilState.Нет и BlendState.AlphaBlend (см. документация MSDN для SpriteBatch.Начать).


решение состоит в том, чтобы добавить следующее Перед 3D-кодом рендеринга:

GraphicsDevice.DepthStencilState = DepthStencilState.Default;

я протестировал этот код перед его отправкой. Создавая новое DepthStencilState, можно задать для свойства GraphicsDevice новое состояние, например:


DepthStencilState d = new DepthStencilState();
d.DepthBufferEnable = true;
GraphicsDevice.DepthStencilState = d;

Как сказал Empyrean, все, что вам нужно сделать, это поместить следующую строку кода непосредственно над кодом, который вы используете для рисования вашей модели в функции Draw ():

GraphicsDevice.DepthStencilState = DepthStencilState.По умолчанию;