Графические примитивы, вершины и буферы вершин

Последнее обновление: 14.11.2015

В прошлой теме мы рассмотрели, как настроить матрицы для установки камеры, видимого пространства сцены и положения объекта в пространстве. Теперь нам собственно надо создать объекты. Для этого изменим код программы следующим образом:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace First3DGame
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Matrix projectionMatrix;
        Matrix viewMatrix;
        Matrix worldMatrix;

        VertexPositionColor[] triangleVertices;
        VertexBuffer vertexBuffer;

        BasicEffect effect;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 6), Vector3.Zero, Vector3.Up);

            projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
                (float)Window.ClientBounds.Width /
                (float)Window.ClientBounds.Height,
                1, 100);

            worldMatrix = Matrix.CreateWorld(new Vector3(0, 0, 0), new Vector3(0, 0, -1), Vector3.Up);

            // создаем набор вершин
            triangleVertices = new VertexPositionColor[3];
            triangleVertices[0] = new VertexPositionColor(new Vector3(0, 1, 0), Color.Red);
            triangleVertices[1] = new VertexPositionColor(new Vector3(1, -1, 0), Color.Green);
            triangleVertices[2] = new VertexPositionColor(new Vector3(-1, -1, 0), Color.Blue);

            // Создаем буфер вершин
            vertexBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor),
                triangleVertices.Length, BufferUsage.None);
            // установка буфера вершин
            vertexBuffer.SetData(triangleVertices);
            // Создаем BasicEffect
            effect = new BasicEffect(GraphicsDevice);
            effect.VertexColorEnabled = true;

            base.Initialize();
        }
        
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
        }

        protected override void UnloadContent()
        {
            
        }
        
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || 
                Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();
            
            base.Update(gameTime);
        }
        
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            // установка буфера вершин
            GraphicsDevice.SetVertexBuffer(vertexBuffer);
            //установка матриц эффекта
            effect.World = worldMatrix;
            effect.View = viewMatrix;
            effect.Projection = projectionMatrix;

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();

                GraphicsDevice.DrawUserPrimitives<VertexPositionColor>
                    (PrimitiveType.TriangleStrip, triangleVertices, 0, 1);
            }

            base.Draw(gameTime);
        }
    }
}

В итоге нам отобразится разноцветный треугольник:

Треугольник в MonoGame

Кроме переменных матриц здесь определяются еще три переменных:

VertexPositionColor[] triangleVertices;
VertexBuffer vertexBuffer;
BasicEffect effect;

Массив объектов VertexPositionColor представляет массив точек нашего объекта - треугольника. Кроме того, нам необходим объект VertexBuffer, представляющий буфер вершин (в который помещаются вершины VertexPositionColor) и передаваемый графическому устройству для отрисовки.

А объект BasicEffect управляет отрисовкой объекта по ранее определенным вершинам.

В методе Initialize() создается три вершины - объекта VertexPositionColor, ровно столько, сколько нам необходимо для отрисовки треугольника:

triangleVertices = new VertexPositionColor[3];
triangleVertices[0] = new VertexPositionColor(new Vector3(0, 1, 0), Color.Red);
triangleVertices[1] = new VertexPositionColor(new Vector3(1, -1, 0), Color.Green);
triangleVertices[2] = new VertexPositionColor(new Vector3(-1, -1, 0), Color.Blue);

Причем каждая вершина определяет не только положение в виде вектора Vector3, но и цвет.

Далее создается и устанавливается буфер вершин:

// Создаем буфер вершин
vertexBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor),
            triangleVertices.Length, BufferUsage.None);
vertexBuffer.SetData(triangleVertices);

Конструктор VertexBuffer принимает два четыре параметра:

  • Графическое устройство - в данном случае объект GraphicsDevice

  • Тип вершин - здесь VertexPositionColor

  • Количество вершин

  • Дополнительная опция поведения в виде перечисления BufferUsage. Оно имеет два значения: None и WriteOnly (буфер вершин только для запис, не для чтения)

И далее с помощью метода SetData() ранее созданный массив объектов VertexPositionColor добавляется в буфер вершин.

И в конце метода Initialize() создается объект BasicEffect:

effect = new BasicEffect(GraphicsDevice);effect.VertexColorEnabled = true;

Свойство VertexColorEnabled позволяет использовать цвета вершин. Если бы оно имело значение false, то мы бы увидели белый треугольник.

Сама отрисовка объекта происходит в методе Draw(). Чтобы отрисовать объект в соответствии с матрицами, нам надо их установить для объекта BasicEffect:

effect.World = worldMatrix;
effect.View = viewMatrix;
effect.Projection = projectionMatrix;

Далее передаем буфер вершин графическому устройству для отрисовки:

GraphicsDevice.SetVertexBuffer(vertexBuffer);

Далее происходит непосредственно отрисовка:

foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
    pass.Apply();

    GraphicsDevice.DrawUserPrimitives<VertexPositionColor>
        (PrimitiveType.TriangleStrip, triangleVertices, 0, 1);
}

Объект BasicEffect имеет одну или несколько техник (объект EffectTechnique). А каждая техника имеет один или несколько проходов (EffectPass). В цикле foreeach проходим по коллекции проходов текущей техники (effect.CurrentTechnique.Passes). Чтобы начать проход для отрисовки техники, нам надо вызвать у каждого прохода метод Apply().

Сам вывод треугольника происходит с помощью метода GraphicsDevice.DrawUserPrimitives. Он типизирован типом вершин - в данном случае типом VertexPositionColor. Он принимает четыре параметра:

  • тип графического примитива. В данном случае PrimitiveType.TriangleStrip, то есть треугольники

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

  • номер вершины в массиве, с которой надо начинать отрисовку, в данном случае число 0

  • количество графических примитивов, в данном случае число 1, так как по трем вершинам последовательно мы можем составить только один треугольник

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850