Проблема с Z-буфером при смешивании 2D-спрайтов с 3D-моделью - PullRequest
8 голосов
/ 14 февраля 2011

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

GraphicsDevice.DepthStencilState.DepthBufferEnable = true;

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

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

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

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

Вот код Draw для справки.

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 ]

8 голосов
/ 15 февраля 2011

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

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

Дополнительные сведения:

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

Вам также нужно установить BlendState на устройстве на BlendState.Opaque.

Вам необходимо установить эти визуализации перед рисованием вашей моделипотому что SpriteBatch.Begin () автоматически изменяет состояние рендеринга на DepthStencilState.None и BlendState.AlphaBlend (см. документацию MSDN для SpriteBatch.Begin ).

4 голосов
/ 12 августа 2011

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

GraphicsDevice.DepthStencilState = DepthStencilState.Default;
1 голос
/ 15 февраля 2011

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

<code>
DepthStencilState d = new DepthStencilState();
d.DepthBufferEnable = true;
GraphicsDevice.DepthStencilState = d;
0 голосов
/ 09 марта 2011

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

GraphicsDevice.DepthStencilState = DepthStencilState.Default;

...