Managed DirectX на C#. Туториалы.
От: mukhomor  
Дата: 07.04.06 18:03
Оценка: 6 (2)
Предлагаю поделиться туториалами Managed DirectX на C#.
Условия такие:
1. Код должен компилироваться на VS2005, при использовании самой свежей версии Managed DirectX.
2. Программа должна быть минимальной!!! в размере кода — 1 лист (и лист с шейдерами, если есть)
3. Если код содран откуда-то, обязательно ссылку.

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

P.S.Если встречу поддержку, со временем могу выложить не менее полусотни таких туториалов.
И повторяюсь — МИНИМУМ кода.
Re: К вопросу об инициализации.
От: mukhomor  
Дата: 07.04.06 18:53
Оценка: 7 (1)
Вот два способа, которыми можно выполнить инициализацию DirectX,
с малым количеством кода. Мои примеры будут использовать их в
зависимости от конкретного случая.

Обычный — используя перерисовку окна событием OnPaint.
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

class WindowsFormDemo : Form
{
    // Создаем устройство
    private Device device = null;
    /// <summary>
    /// конструктор
    /// </summary>
    public WindowsFormDemo()
    {
        // заголовок окна
        this.Text = "Инициализация устройства DirectX";
        // минимальные размеры окна
        this.MinimumSize = new Size(50, 100);
        // размер клиентской области
        this.ClientSize = new Size(640, 480);
    }
    public void InitializeGraphics()
    {
        // параметры представления
        PresentParameters presentParams = new PresentParameters();
        // работает ли приложение в полноэкранном режиме - да.
        presentParams.IsWindowed = true;
        // режим работы буферной подкачки
        presentParams.SwapEffect = SwapEffect.Discard;

        // Инициализация устройства.
        device = new Device(0,   // идентификатор адаптера 
            DeviceType.Hardware, // тип устройства 
            this.Handle,         // дескриптор окна визуализации
            CreateFlags.SoftwareVertexProcessing,  // флаг режима работы устройства
            presentParams);      // параметры представления
    }
    public static void Main()
    {
        using (WindowsFormDemo frm = new WindowsFormDemo())
        {
            frm.InitializeGraphics(); // Инициализация графического устройства
            Application.Run(frm);
        }
    }

    ////////////////////////////////////////////////////////
    //---------------------------------------------------------------------------------------
    // Метод: void OnPaint(System.Windows.Forms.PaintEventArgs e)
    //
    // Цель: Обработка события Paint
    //---------------------------------------------------------------------------------------
    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
    {
        device.Clear(ClearFlags.Target,    // что именно хотим очистить (текущее окно) 
                     System.Drawing.Color.Black, // цвет очистки
                     1.0f, // буфер глубины.( Число 0.0 представляет 
            // самое близкое расстояние к зрителю; число 1.0 представляет 
            // самое дальнее расстояние.
                     0);
        device.Present();
    }
}



Этот способ позаимствован из SDK. С его помощью можно находить гораздо более
эффективные решения:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

class MyDirect : Form
{
    // Создаем устройство
    private Device device = null;
    /// <summary>
    /// Точка входа в приложение.
    /// </summary>
    [STAThread] // аттрибут указывает на то, что поточная модель 
    // COM для приложения является однопоточной средой (STA).
    public static void Main()
    {
        using (MyDirect frm = new MyDirect())
        {
            Application.Idle += new EventHandler(frm.OnApplicationIdle);
            // Application.Idle -  Событие, которое происходит, когда 
            // приложение заканчивает обработку и собирается перейти 
            // в состояние незанятости.
            frm.InitializeGraphics();
            Application.Run(frm);
        }
    }
    /// <summary>
    /// Инициализация устройства DirectX
    /// </summary>
    public void InitializeGraphics()
    {
        // параметры представления
        PresentParameters presentParams = new PresentParameters();
        // работает ли приложение в полноэкранном режиме - да.
        presentParams.IsWindowed = true;
        // режим работы буферной подкачки
        presentParams.SwapEffect = SwapEffect.Discard;

        // Инициализация устройства.
        device = new Device(0,   // идентификатор адаптера 
            DeviceType.Hardware, // тип устройства 
            this.Handle,         // дескриптор окна визуализации
            CreateFlags.SoftwareVertexProcessing,  // флаг режима работы устройства
            presentParams);      // параметры представления
    }

    /// <summary>
    /// Содержимое функции будет выполнено, если нет сообщений,
    /// т.е. в момент простоя
    /// </summary>
    /// <param name="sender">Sending object</param>
    /// <param name="e">Event arguments</param>
    private void OnApplicationIdle(object sender, EventArgs e)
    {
        while (AppStillIdle)
        {
            device.Clear(ClearFlags.Target,    // что именно хотим очистить (текущее окно) 
                     System.Drawing.Color.Black, // цвет очистки
                     1.0f, // буфер глубины.( Число 0.0 представляет 
                     // самое близкое расстояние к зрителю; число 1.0 представляет 
                     // самое дальнее расстояние.
                     0);
            //...................................
            // Здесь будет происходить прорисовка
            //...................................
            device.Present();
        }
    }

    /// <summary>
    /// Выясняется, поступало ли сообщение.
    /// true - если не поступало, false - если поступало.
    /// </summary>
    private bool AppStillIdle
    {
        get
        {
            NativeMethods.Message msg;
            return !NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
        }
    }

    /// <summary>
    /// Общее описание NativeMethods.
    /// </summary>
    public class NativeMethods
    {
        /// <summary>Сообщения Windows</summary>
        /*   Класс StructLayoutAttribute позволяет пользователю 
         * управлять физическим размещением полей данных класса или 
         * структуры.
         *   LayoutKind - управляет макетом объекта при его экспорте 
         * в неуправляемый код.
         *   Sequential - члены объекта располагаются последовательно, 
         * в порядке, в котором они появляются при экспортировании 
         * в неуправляемую память. Члены располагаются в соответствии 
         * с заданной в StructLayoutAttribute.Pack компоновкой и 
         * могут быть независимыми.*/
        [StructLayout(LayoutKind.Sequential)] // аттрибут
        public struct Message
        {
            public IntPtr hWnd;
            public uint msg;
            public IntPtr wParam;
            public IntPtr lParam;
            public uint time;
            public System.Drawing.Point p;
        }

        /*System.Security.SuppressUnmanagedCodeSecurity - 
         * позволяет управляемому коду передавать управление 
         * неуправляемому коду без проверки стека. */
        [System.Security.SuppressUnmanagedCodeSecurity] // аттрибут
        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax, uint flags);
    }

}
Re: Треугольник. Без него - никуда :)
От: mukhomor  
Дата: 08.04.06 18:57
Оценка: 7 (1)
Своеобразным "Hello World!" в программировании графики является вывод
трехмерного треугольника на экран. Этот пример полезен для новичков,
поскольку демонстрирует сразу несколько элементов:
прорисовка примитива с использованием GraphicsBuffer,
установка проекции и камеры, трансформирование мировых координат.

Источник: это известный пример, но адаптированный мной под
b-версию Managed DirectX. Для гладкой работы приложения
использовано событие OnResize(), в момент которого очищается устройство.
(посмотрите, что будет, если этого не сделать.)

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


//-----------------------------------------------------------------
// Трехмерный треугольник. Вращение треугольника.
//-----------------------------------------------------------------

using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.Generic;
using Microsoft.DirectX.Direct3D.CustomVertex;

class WindowsFormDemo : Form
{
    // Создаем устройство
    private Device device = null;
    // параметры представления
    PresentParameters presentParams = new PresentParameters();
    // Переменная, используемая при вращении объекта.
    private float angle = 0.0f;

    /// <summary>
    /// конструктор
    /// </summary>
    public WindowsFormDemo()
    {
        // заголовок окна
        this.Text = "Инициализация устройства DirectX";
        // минимальные размеры окна
        this.MinimumSize = new Size(50, 100);
        // размер клиентской области
        this.ClientSize = new Size(640, 480);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
    }
    /// <summary> Инициализация графического устройства </summary>
    public void InitializeGraphics()
    {
        if (BuildPresentParameters())
        {
            // Инициализация устройства.
            device = new Device(0, DeviceType.Hardware, this.Handle,
                CreateFlags.SoftwareVertexProcessing, presentParams);
        }
        else
        {
            Console.WriteLine("Устройство не построено!");
            return;
        }
    }

    /// <summary> Задаем параметры представления. </summary>
    public bool BuildPresentParameters()
    {
        presentParams = new PresentParameters();
        presentParams.SwapEffect = SwapEffect.Discard;
        presentParams.IsWindowed = true;
        return true;
    }
    /// <summary> Строим камеру. </summary>
    private void SetupCamera()
    {
        // Параметры камеры
        device.Transform.Projection =
            // представление поля y (угол при вершине пирамиды).
            Matrix.PerspectiveFieldOfViewLeftHanded((float)Math.PI / 4,
            (float)this.Width / this.Height, 1.0f, 100.0f);
        // Установка камеры
        device.Transform.View =
            // положение камеры во внешней системе координат
            Matrix.LookAtLeftHanded(new Vector3(0, 0, 5.0f),
            // местоположение объекта, на который нацелена камера
            new Vector3(),
            // направление камеры (у нас - вверх). 
            new Vector3(0, 1, 0));
        //-----!!!----- Вращение объекта относительно оси Z  
        //device.Transform.World = Matrix.RotationZ((float)Math.PI/6.0f);
        //device.Transform.World = Matrix.RotationY((System.Environment.TickCount / 25.0f) / (float)Math.PI / 6);
        //device.Transform.World = Matrix.RotationZ(angle/(float)Math.PI);
        // В следующей функции мы сначала определяем ось, вокруг которой намерены
        // вращать треугольник, а затем вводим угол поворота.
        device.Transform.World = Matrix.RotationAxis(
           new Vector3(angle / ((float)Math.PI * 2.0f), 
            angle / ((float)Math.PI * 4.0f),
            angle / ((float)Math.PI * 6.0f)),
            angle / (float)Math.PI);
        angle += 0.06f; // такой подход вообще говоря не оправдан, поскольку скорость 
        // вращения зависит от мощности компьютера


        // Отключим освещение в сцене. Это позволяет видеть объект
        // в обычном режиме без установки нормалей. 
        device.RenderState.Lighting = false;

        //----!!!Режим отбора и устранения(исключени невидимой поверхности)
        // В таком режиме, треугольник не исчезает при вращении, обернувшись
        // к нам задней поверхностью.
        device.RenderState.CullMode = Cull.None;

    }
    /// <summary> Точка входа в приложение </summary>
    public static void Main()
    {
        using (WindowsFormDemo frm = new WindowsFormDemo())
        {
            try
            {
                frm.InitializeGraphics(); // Инициализация графического устройства
            }
            catch
            {
                MessageBox.Show("Инициализация DirectX не выполнена!");
            }
            Application.Run(frm);
        }
    }

    /// <summary> Обработка события Paint </summary>
    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
    {
        device.Clear(ClearFlags.Target,    // что именно хотим очистить (текущее окно) 
                     System.Drawing.Color.Black, // цвет очистки
                     1.0f, // буфер глубины.
                     0);
        SetupCamera();  //  Установка камеры
        //Рисуем треугольник 
        GraphicsBuffer<PositionColored> verts = new GraphicsBuffer<PositionColored>(3);

        verts[0] =
            new PositionColored(0.0f, 1.0f, 0.0f, System.Drawing.Color.Green);
        verts[1] =
            new PositionColored(-1.0f, -1.0f, 1.0f, System.Drawing.Color.Blue);
        verts[2] =
            new PositionColored(1.0f, -1.0f, 1.0f, System.Drawing.Color.Purple);


        device.BeginScene();

        device.VertexFormat = PositionColored.Format;
        device.DrawUserPrimitives(PrimitiveType.TriangleList, 1, verts);

        device.EndScene();
        device.Present();
        this.Invalidate();
    }

    /// <summary> Обработка события OnResize() </summary>
    protected override void OnResize(EventArgs e)
    {
        if (this.WindowState == FormWindowState.Minimized)
        {
            return;
        }
        if (device != null)
        {
            if (!BuildPresentParameters())
            {
                throw new Exception("Устройство сбросить невозможно!");
            }
            device.Reset(presentParams);
        }
        base.OnResize(e);
    }

}
Re: Managed DirectX на C#. Туториалы.
От: Didro Россия home~pages
Дата: 08.04.06 22:29
Оценка: 2 (1)
Здравствуйте, mukhomor, Вы писали:

M>Предлагаю поделиться туториалами Managed DirectX на C#.

Думаю, что всем известный сайт(да и не русский к тому же, зато обновляется часто) но всё-таки:

http://www.c-unit.com/tutorials/mdirectx/
Re: Работа с текстурами
От: mukhomor  
Дата: 07.04.06 18:05
Оценка:
Для примера, выкладываю демонстрацию альфа-смешивания.
Запуск — copy/paste в Empty Project на C#. Используется DirectX 2-й версии.
!!!В директиву с кодом добавьте произвольные 3 файла формата JPEG : tex1.jpg, tex2.jpg, tex3.jpg,
которые будут использоваться как текстуры.

//-----------------------------------------------------------------
// Альфа-смешивание. Задается порог смешивания.
//-----------------------------------------------------------------

/* Пример Альфа- смешивания текстурированных объектов*/


using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.Generic;
using Microsoft.DirectX.Direct3D.CustomVertex;

class WindowsFormDemo : Form
{
    // Создаем устройство
    private Device device = null;
    // параметры представления
    PresentParameters presentParams = new PresentParameters();
    private VertexBuffer vb_cube;
    Texture tex1;
    Texture tex2;
    Texture tex3;
    float angle = 0.0f;

    private Microsoft.DirectX.Direct3D.Font font = null;

    int blendfactor = 128;///////////////////////////////

    /// <summary>
    /// конструктор
    /// </summary>
    public WindowsFormDemo()
    {
        this.Text = "Инициализация устройства DirectX";
        this.MinimumSize = new Size(50, 100);
        this.ClientSize = new Size(640, 480);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
    }
    /// <summary> Инициализация графического устройства </summary>
    public void InitializeGraphics()
    {
        if (BuildPresentParameters())
        {
            // Инициализация устройства.
            device = new Device(0, DeviceType.Hardware, this.Handle,
                CreateFlags.SoftwareVertexProcessing, presentParams);
        }
        else
        {
            Console.WriteLine("Устройство не построено!");
            return;
        }

        InitCube();

        font = new Microsoft.DirectX.Direct3D.Font(device, new System.Drawing.Font
                    ("Arial", 12.0f, FontStyle.Bold | FontStyle.Italic));

        // Load the texture
        tex1 = new Texture(device, "..\\..\\tex1.jpg");
        tex2 = new Texture(device, "..\\..\\tex2.jpg");
        tex3 = new Texture(device, "..\\..\\tex3.jpg");
    }



    /// <summary> Задаем параметры представления. </summary>
    public bool BuildPresentParameters()
    {
        presentParams = new PresentParameters();
        presentParams.SwapEffect = SwapEffect.Discard;
        presentParams.IsWindowed = true;
        presentParams.EnableAutoDepthStencil = true;
        presentParams.AutoDepthStencilFormat = DepthFormat.D16;

        return true;
    }
    /// <summary> Строим камеру. </summary>
    private void SetupCamera()
    {
        // Параметры камеры
        device.Transform.Projection =
            Matrix.PerspectiveFieldOfViewLeftHanded((float)Math.PI / 4,
            (float)this.Width / (float)this.Height, 1.0f, 100.0f);
        // Установка камеры
        device.Transform.View =
            Matrix.LookAtLeftHanded(new Vector3(0, 0, -9.0f),
            new Vector3(),
            new Vector3(0, 1, 0));
        device.Transform.World = Matrix.RotationY(angle / (float)Math.PI * 4.0f) *
            Matrix.RotationZ(angle / (float)Math.PI * 4.0f) *
            Matrix.RotationX(angle / (float)Math.PI * 4.0f);

        // Отключаем освещение
        device.RenderState.Lighting = false;
        //Режим отбора и устранения(исключени невидимой поверхности)
        device.RenderState.CullMode = Cull.None;

        // устанавливаем параметры смешивания
        SetAlphablending();
    }
    public void SetAlphablending()//////////////////////////////////////////////////////////////////////
    {
        device.RenderState.AlphaBlendEnable = true;
        device.RenderState.BlendOperation = BlendOperation.Add;
        device.RenderState.SourceBlend = Blend.BlendFactor;/////////////////////////////////////////////
        device.RenderState.DestinationBlend = Blend.InvBlendFactor;/////////////////////////////////////

        device.RenderState.BlendFactor = Color.FromArgb(blendfactor, blendfactor, blendfactor, blendfactor);/////////
    }

    /// <summary> Точка входа в приложение </summary>
    public static void Main()
    {
        using (WindowsFormDemo frm = new WindowsFormDemo())
        {
            try
            {
                frm.InitializeGraphics(); // Инициализация графического устройства
            }
            catch
            {
                MessageBox.Show("Инициализация DirectX не выполнена!");
            }
            Application.Run(frm);
        }
    }

    /// <summary> Обработка события Paint </summary>
    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
    {
        device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,    // что именно хотим очистить (текущее окно) 
                     System.Drawing.Color.Black, // цвет очистки
                     1.0f, // буфер глубины.
                     0);

        angle += 0.01f;
        SetupCamera();  //  Установка камеры


        device.BeginScene();

        // Отобразим текст
        #region поясняющий текст
        font.DrawString(null, string.Format("Используйте клавиши Up, Down."), new Rectangle(10, 0, 0, 0),
            DrawStringFormat.NoClip, Color.BlanchedAlmond);

        font.DrawString(null, string.Format("Blendfactor:  {0}",
           blendfactor.ToString()), new Rectangle(10, 20, 0, 0),
           DrawStringFormat.NoClip, Color.BlanchedAlmond);
        #endregion

        #region рисуем кубики///////////////////

        // !!! Альфа смешивание зависит от порядка построения кубов.
        // сначала рисуется внутрениий и т.д.

        // Обрати внимание на этот прием!
        // Исключаем смешивание с фоном самого маленького кубика
        device.RenderState.AlphaBlendEnable = false;//////////////////////////////////////
        DrawСube(angle / (float)Math.PI,
           angle / (float)Math.PI * 1.0f,
           angle / (float)Math.PI / 8.0f,
           0.0f, 0.0f, 0.0f,
           new Vector3(0.5f, 0.5f, 0.5f),
           tex3);
        device.RenderState.AlphaBlendEnable = true;////////////////////////////////////////
        DrawСube(angle / (float)Math.PI,
            angle / (float)Math.PI * 2.0f,
            angle / (float)Math.PI / 4.0f,
            0.0f, 0.0f, 0.0f,
            new Vector3(1.0f, 1.0f, 1.0f),
            tex2);

        DrawСube(angle / (float)Math.PI,
           angle / (float)Math.PI * 5.0f,
            angle / (float)Math.PI / 8.0f,
            0.0f, 0.0f, 0.0f,
           new Vector3(2.0f, 2.0f, 2.0f),
            tex1);
        #endregion

        device.EndScene();
        device.Present();
        this.Invalidate();
    }

    /// <summary> Обработка события OnResize() </summary>
    protected override void OnResize(EventArgs e)
    {
        if (this.WindowState == FormWindowState.Minimized)
        {
            return;
        }
        if (device != null)
        {
            if (!BuildPresentParameters())
            {
                throw new Exception("Устройство сбросить невозможно!");
            }
            font.OnLostDevice();
            device.Reset(presentParams);
        }
        base.OnResize(e);
    }

    private void InitCube()
    {

        PositionColoredTextured[] verts = {
                new PositionColoredTextured( -1.0f,  1.0f, -1.0f, Color.White, 0.0f, 0.0f ),
                new PositionColoredTextured(  1.0f,  1.0f, -1.0f, Color.White, 1.0f, 0.0f ),
                new PositionColoredTextured(  1.0f, -1.0f, -1.0f, Color.White, 1.0f, 1.0f ),
                new PositionColoredTextured( -1.0f,  1.0f, -1.0f, Color.White, 0.0f, 0.0f ),
                new PositionColoredTextured(  1.0f, -1.0f, -1.0f, Color.White, 1.0f, 1.0f ),
                new PositionColoredTextured( -1.0f, -1.0f, -1.0f, Color.White, 0.0f, 1.0f ),

                new PositionColoredTextured(  1.0f,  1.0f, -1.0f, Color.White, 0.0f, 0.0f ),
                new PositionColoredTextured(  1.0f,  1.0f,  1.0f, Color.White, 1.0f, 0.0f ),
                new PositionColoredTextured(  1.0f, -1.0f,  1.0f, Color.White, 1.0f, 1.0f ),
                new PositionColoredTextured(  1.0f,  1.0f, -1.0f, Color.White, 0.0f, 0.0f ),
                new PositionColoredTextured(  1.0f, -1.0f,  1.0f, Color.White, 1.0f, 1.0f ),
                new PositionColoredTextured(  1.0f, -1.0f, -1.0f, Color.White, 0.0f, 1.0f ),

                new PositionColoredTextured(  1.0f,  1.0f,  1.0f, Color.White, 0.0f, 0.0f ),
                new PositionColoredTextured( -1.0f,  1.0f,  1.0f, Color.White, 1.0f, 0.0f ),
                new PositionColoredTextured( -1.0f, -1.0f,  1.0f, Color.White, 1.0f, 1.0f ),
                new PositionColoredTextured(  1.0f,  1.0f,  1.0f, Color.White, 0.0f, 0.0f ),
                new PositionColoredTextured( -1.0f, -1.0f,  1.0f, Color.White, 1.0f, 1.0f ),
                new PositionColoredTextured(  1.0f, -1.0f,  1.0f, Color.White, 0.0f, 1.0f ),

                new PositionColoredTextured( -1.0f,  1.0f,  1.0f, Color.White, 0.0f, 0.0f ),
                new PositionColoredTextured( -1.0f,  1.0f, -1.0f, Color.White, 1.0f, 0.0f ),
                new PositionColoredTextured( -1.0f, -1.0f, -1.0f, Color.White, 1.0f, 1.0f ),
                new PositionColoredTextured( -1.0f,  1.0f,  1.0f, Color.White, 0.0f, 0.0f ),
                new PositionColoredTextured( -1.0f, -1.0f, -1.0f, Color.White, 1.0f, 1.0f ),
                new PositionColoredTextured( -1.0f, -1.0f,  1.0f, Color.White, 0.0f, 1.0f ),

                new PositionColoredTextured( -1.0f,  1.0f,  1.0f, Color.White,  0.0f, 0.0f ),
                new PositionColoredTextured(  1.0f,  1.0f,  1.0f, Color.White, 1.0f, 0.0f ),
                new PositionColoredTextured(  1.0f,  1.0f, -1.0f, Color.White,   1.0f, 1.0f ),
                new PositionColoredTextured( -1.0f,  1.0f,  1.0f, Color.White,  0.0f, 0.0f ),
                new PositionColoredTextured(  1.0f,  1.0f, -1.0f, Color.White,   1.0f, 1.0f ),
                new PositionColoredTextured( -1.0f,  1.0f, -1.0f, Color.White,0.0f, 1.0f ),

                new PositionColoredTextured( -1.0f, -1.0f, -1.0f, Color.White, 0.0f, 0.0f ),
                new PositionColoredTextured(  1.0f, -1.0f, -1.0f, Color.White, 1.0f, 0.0f ),
                new PositionColoredTextured(  1.0f, -1.0f,  1.0f, Color.White, 1.0f, 1.0f ),
                new PositionColoredTextured( -1.0f, -1.0f, -1.0f, Color.White, 0.0f, 0.0f ),
                new PositionColoredTextured(  1.0f, -1.0f,  1.0f, Color.White, 1.0f, 1.0f ),
                new PositionColoredTextured( -1.0f, -1.0f,  1.0f, Color.White, 0.0f, 1.0f )
            };

        // Вершинный буфер
        vb_cube = new VertexBuffer(device,
            verts.Length * PositionColoredTextured.StrideSize,
            Usage.WriteOnly,
            PositionColoredTextured.Format,
            Pool.Managed,
            null);
        GraphicsBuffer<PositionColoredTextured> buffer = vb_cube.Lock<PositionColoredTextured>(0, 0, LockFlags.None);
        buffer.Write(verts);
        vb_cube.Unlock();
        buffer.Dispose();
    }

    private void DrawСube(float yaw, float pitch, float roll, float x, float y, float z, Vector3 scale, Texture t)
    {
        device.Transform.World = Matrix.Scaling(scale) * Matrix.RotationYawPitchRoll(yaw, pitch, roll) * Matrix.Translation(x, y, z);
        device.VertexFormat = PositionColoredTextured.Format;
        device.SetTexture(0, t);
        device.SetStreamSource(0, vb_cube, 0, PositionColoredTextured.StrideSize);
        device.DrawPrimitives(PrimitiveType.TriangleList, 0, 12);
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        switch (e.KeyCode)
        {
            case Keys.Up://////////////////////////////////////////////////////////
                blendfactor += 2;
                if (blendfactor > 255) blendfactor = 255;
                break;
            case Keys.Down:////////////////////////////////////////////////////////
                blendfactor -= 2;
                if (blendfactor < 0) blendfactor = 0;
                break;
            default:
                break;
        }

        SetAlphablending();
        base.OnKeyDown(e);
    }


}
Re[2]: Треугольник. NativeMethods.
От: mukhomor  
Дата: 08.04.06 20:29
Оценка:
Для сравнения приведу программу с использованием NativeMethods.
Вы можете увидеть, насколько более плавным стало вращение треугольника.
Остаточные рывки связаны с приращением параметра angle.
Когда речь дойдет до FPS, будет отчетливо видно, что количество кадров
в сек заметно возросло.


using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.Generic;
using Microsoft.DirectX.Direct3D.CustomVertex;

namespace DxFrameworkSample
{

    class MyDirect : Form
    {
        private Device device = null;
        // параметры представления
        PresentParameters presentParams = new PresentParameters();
        private float angle = 0.0f;

        public MyDirect()
        {
            // заголовок окна
            this.Text = "Инициализация устройства DirectX";
            // минимальные размеры окна
            this.MinimumSize = new Size(50, 100);
            // размер клиентской области
            this.ClientSize = new Size(640, 480);
        }

        /// <summary>
        /// Точка входа в приложение.
        /// </summary>
        [STAThread]
        public static void Main()
        {
            using (MyDirect frm = new MyDirect())
            {
                Application.Idle += new EventHandler(frm.OnApplicationIdle);
                frm.InitializeGraphics();
                Application.Run(frm);
            }
        }

        /// <summary> Параметры представления   </summary>
        public bool BuildPresentParameters()
        {
            presentParams = new PresentParameters();
            presentParams.SwapEffect = SwapEffect.Discard;
            presentParams.IsWindowed = true;
            return true;
        }

        /// <summary> Инициализация графического устройства </summary>
        public void InitializeGraphics()
        {
            if (BuildPresentParameters())
            {
                // Инициализация устройства.
                device = new Device(0, DeviceType.Hardware, this.Handle,
                    CreateFlags.SoftwareVertexProcessing, presentParams);
            }
            else
            {
                Console.WriteLine("Устройство не построено!");
                return;
            }
        }
        /// <summary> Строим камеру. </summary>
        private void SetupCamera()
        {
            // Параметры камеры
            device.Transform.Projection =
                // представление поля y (угол при вершине пирамиды).
                Matrix.PerspectiveFieldOfViewLeftHanded((float)Math.PI / 4,
                (float)this.Width / this.Height, 1.0f, 100.0f);
            // Установка камеры
            device.Transform.View =
                // положение камеры во внешней системе координат
                Matrix.LookAtLeftHanded(new Vector3(0, 0, 5.0f),
                // местоположение объекта, на который нацелена камера
                new Vector3(),
                // направление камеры (у нас - вверх). 
                new Vector3(0, 1, 0));
           
            device.Transform.World = Matrix.RotationAxis(
                new Vector3(angle / ((float)Math.PI * 2.0f), 
                angle / ((float)Math.PI * 4.0f),
                angle / ((float)Math.PI * 6.0f)),
                angle / (float)Math.PI);
             

            device.RenderState.Lighting = false;

            //Режим отбора
            device.RenderState.CullMode = Cull.None;

        }
        /// <summary> Прорисовка </summary>
        private void RenderFrame()
        {
            device.Clear(ClearFlags.Target,
                    System.Drawing.Color.Black,
                    1.0f,
                    0);
            SetupCamera();
            //----------------------- Рисуем треугольник ----------------------------------------
            GraphicsBuffer<PositionColored> verts = new GraphicsBuffer<PositionColored>(3);

            verts[0] =
                new PositionColored(0.0f, 1.0f, 0.0f, System.Drawing.Color.HotPink);
            verts[1] =
                new PositionColored(-1.0f, -1.0f, 1.0f, System.Drawing.Color.Peru);
            verts[2] =
                new PositionColored(1.0f, -1.0f, 1.0f, System.Drawing.Color.Purple);
            /* Замечание: обратите внимание на то, в какой последовательности рисуются вершины. */
            device.BeginScene();

            device.VertexFormat = PositionColored.Format;
            device.DrawUserPrimitives(PrimitiveType.TriangleList, 1, verts);

            device.EndScene();

            device.Present();
        }
        /// <summary>
        /// Обновление параметров анимации
        /// </summary>
        private void UpdateFrame()
        {
            angle += 0.06f;
        }
        protected override void OnResize(EventArgs e)
        {
            //!!! Если не исключить случай минимизации окна, в приложении
            // произойдет ошибка!
            if (this.WindowState == FormWindowState.Minimized)
            {
                return;
            }
            if (device != null)
            {
                if (!BuildPresentParameters())
                {
                    throw new Exception("Устройство сбросить невозможно!");
                }
                device.Reset(presentParams);
            }
            base.OnResize(e);
        }
        /// <summary>
        /// Содержимое функции будет выполнено, если нет сообщений,
        /// т.е. в момент простоя
        /// </summary>
        private void OnApplicationIdle(object sender, EventArgs e)
        {
            while (AppStillIdle)
            {
                //...................................
                UpdateFrame();
                RenderFrame();
                //...................................
            }
        }
        /// <summary>
        /// Выясняется, поступало ли сообщение.
        /// true - если не поступало, false - если поступало.
        /// </summary>
        private bool AppStillIdle
        {
            get
            {
                NativeMethods.Message msg;
                return !NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
            }
        }

    }

    #region Native
    public class NativeMethods
    {
        /// <summary>Сообщения Windows</summary>
        [StructLayout(LayoutKind.Sequential)] // аттрибут
        public struct Message
        {
            public IntPtr hWnd;
            public uint msg;
            public IntPtr wParam;
            public IntPtr lParam;
            public uint time;
            public System.Drawing.Point p;
        }
        [System.Security.SuppressUnmanagedCodeSecurity] // аттрибут
        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax, uint flags);
    }
    #endregion
}
Re: Mesh.
От: mukhomor  
Дата: 09.04.06 12:27
Оценка:
В начале обучения Managed DirectX наибольший интерес представляют два
объекта — mesh и sprite. Поэтому, забегая вперед, сначала покажу, как подгрузить
mesh.

Как запустить: 1. В папке Solution (или просто на одном уровне с проектом) создайте
дополнительную папку Media. В нее скопируйте любой .x файл из одноименной папки SDK,
включая текстуры к нему. Например, LandShark.x
2. Остальное, как обычно — copy/paste в empty project.

Сделать свой сбственный .x файл можно, если использовать, в частности, конвертор
из того же SDK. На мой взгляд, самый эффективный способ это использовать
предустановленное SDK для 3ds max или Maya и скомпилировать проект из
...Utilites\Source\Max(Maya) в папке SDK к VS. Так в папке Plugins для 3ds max
появится конвертор. А дальше просто : File > Save As...


/* Для работы с Mesh нам необходима различная информация о поверхности.
 Например, нас интересует количество вершин, граней, текстур и, конечно,
 размеры объекта.
 *  Выведем на экран информацию о количестве вершин и граней. Кроме этого,
 * трансформируем объект под нашу камеру.
 */

using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.Generic;
using Microsoft.DirectX.Direct3D.CustomVertex;

class WindowsFormDemo : Form
{
    // Создаем устройство
    private Device device = null;
    // параметры представления
    PresentParameters presentParams = new PresentParameters();
    private float angle = 0.0f;

    private Microsoft.DirectX.Direct3D.Font font = null; /////////////////////////////////////

    // Объект типа Mesh
    Mesh mesh = null;
    Material[] meshMaterials;
    BaseTexture[] meshTextures;
    string FilePath = "..\\..\\..\\Media\\";// Путь к файлу с Mesh
    //string FileName = "tiny.x";// имя .x файла
    //string FileName = "LandShark.x";// имя .x файла
    string FileName = "Dwarf.x";// имя .x файла
    private Vector3 objectCenter; // центр ограничивающей сферы//////////////////////////////////
    private float objectRadius; // радиус ограничивающей сферы///////////////////////////////////
    private Matrix worldCenter; // мировая матрица для размещения mesh///////////////////////////


    /// <summary>
    /// конструктор
    /// </summary>
    public WindowsFormDemo()
    {
        this.Text = "Mesh - примитивы.";
        this.MinimumSize = new Size(50, 100);
        this.ClientSize = new Size(640, 480);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
    }
    /// <summary> Инициализация графического устройства </summary>
    public void InitializeGraphics()
    {
                         
        if (BuildPresentParameters())
        {
            // Инициализация устройства.
            device = new Device(0, DeviceType.Hardware, this.Handle,
                CreateFlags.SoftwareVertexProcessing, presentParams);
        }
        else
        {
            Console.WriteLine("Устройство не построено!");
            return;
        }
        font = new Microsoft.DirectX.Direct3D.Font(device, new System.Drawing.Font//////////////////////////////
                    ("Arial", 14.0f, FontStyle.Bold | FontStyle.Italic));    
        LoadMesh(FileName);
    }

    /// <summary> Задаем параметры представления. </summary>
    public bool BuildPresentParameters()
    {
        presentParams = new PresentParameters();
        presentParams.SwapEffect = SwapEffect.Discard;
        presentParams.IsWindowed = true;
        presentParams.EnableAutoDepthStencil = true;
        presentParams.AutoDepthStencilFormat = DepthFormat.D16;

        return true;
    }
    /// <summary> Строим камеру. </summary>
    private void SetupCamera()
    {
        device.Transform.Projection = 
            Matrix.PerspectiveFieldOfViewLeftHanded(
            (float)Math.PI / 4, 
            (float)this.ClientSize.Width / this.ClientSize.Height, 
            1.0f, 
            100.0f);
        device.Transform.View = Matrix.LookAtLeftHanded(
            new Vector3(0, 0, -5.0f), 
            new Vector3(), 
            new Vector3(0, 1, 0));
        device.RenderState.Ambient = Color.White;
        device.Lights[0].LightType = LightType.Directional;
        device.Lights[0].Diffuse = Color.White;
        device.Lights[0].Direction = new Vector3(0, -1, 5);
        device.Lights[0].Enabled = true;

        //Режим отбора и устранения(исключени невидимой поверхности)
        //device.RenderState.CullMode = Cull.CounterClockwise;

    }
    /// <summary> Точка входа в приложение </summary>
    public static void Main()
    {
        using (WindowsFormDemo frm = new WindowsFormDemo())
        {
            try
            {
                frm.InitializeGraphics(); // Инициализация графического устройства
            }
            catch
            {
                MessageBox.Show("Инициализация DirectX не выполнена!");
            }
            Application.Run(frm);
        }
    }

    /// <summary> Обработка события Paint </summary>
    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
    {
        angle += 0.01f;

        device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,    // что именно хотим очистить (текущее окно) 
                     System.Drawing.Color.Blue, // цвет очистки
                     1.0f, // буфер глубины.
                     0);
        device.Transform.World = worldCenter*Matrix.RotationYawPitchRoll(angle / (float)Math.PI,//////////////////
            angle / (float)Math.PI * 2.0f,
            angle / (float)Math.PI / 4.0f);
        SetupCamera();  //  Установка камеры

        device.BeginScene();
        for (int i = 0; i < meshMaterials.Length; i++)
        {
            device.Material = meshMaterials[i];
            device.SetTexture(0, meshTextures[i]);
            mesh.DrawSubset(i);
        }
        // Отобразим текст
        font.DrawString(null, string.Format("Количество вершин: {0}",/////////////////////////////
            mesh.VertexCount), new Rectangle(10, 10, 0, 0),
            DrawStringFormat.NoClip, Color.BlanchedAlmond);

        font.DrawString(null, string.Format("Количество граней: {0}",/////////////////////////////
            mesh.FaceCount), new Rectangle(10, 30, 0, 0),
            DrawStringFormat.NoClip, Color.BlanchedAlmond);


        device.EndScene();
        device.Present();
        this.Invalidate();
    }

    /// <summary>
    /// Загрузка Mesh объекта из файла
    /// </summary>
    /// <param name="file">Имя файла.</param>
    private void LoadMesh(string file)
    {

        GraphicsBuffer outputAdjacency = new GraphicsBuffer();
        MaterialList materials = new MaterialList();
        EffectInstanceList effects = new EffectInstanceList();
        // Загрузка поверхности
        mesh = new Mesh(device, FilePath + FileName, MeshFlags.Managed, outputAdjacency, materials, effects);
        // эффекты не используются
        effects.Dispose();
        using (outputAdjacency)
        {
            // Оптимизируем mesh для работы
            mesh.OptimizeInPlace(MeshFlags.OptimizeVertexCache | MeshFlags.OptimizeCompact |
                MeshFlags.OptimizeAttributeSort, outputAdjacency);
        }

        // Поиск параметров ограничительной сферы и матрицы центрирования
        using (VertexBuffer vb = mesh.VertexBuffer)//////////////////////////////////////////////////////
        {
            // блокируем буфер для извлечения параметров
            using (GraphicsBuffer stm = vb.Lock(0, 0, LockFlags.NoSystemLock))
            {
                try
                {
                    // ограничительная сфера
                    BoundingSphere bs = Geometry.ComputeBoundingSphere(stm,
                        mesh.VertexCount, mesh.VertexFormat);
                    // ее радиус
                    objectRadius = bs.Radius;
                    //Console.WriteLine(objectRadius);
                    //Console.WriteLine(objectCenter.ToString());
                    
                    // ее центр
                    objectCenter = bs.Center;

                    // паралельный перенос
                    worldCenter = Matrix.Translation(-objectCenter);
                    // коэффициент сжатия
                    float scaleFactor = 2.0f / objectRadius;
                    // масштабирование
                    worldCenter *= Matrix.Scaling(scaleFactor, scaleFactor, scaleFactor);
                }
                finally
                {
                    // разблокируем буффер
                    vb.Unlock();
                }
            }
        }

        // Имеются ли материалы?
        if ((materials != null) && (materials.Count > 0))
        {
            // Массивы для хранения материалов и текстур
            meshMaterials = new Material[materials.Count];
            meshTextures = new BaseTexture[materials.Count];

            // Скопируем каждый материал и восстановим текстуры
            for (int i = 0; i < materials.Count; i++)
            {
                // сначала копируем материал
                meshMaterials[i] = materials[i].Material;

                // Имеется ли у данного материала текстура??
                if (string.IsNullOrEmpty(materials[i].TextureFileName))
                    continue; // Если да - продолжим...

                ImageInformation info = new ImageInformation();
                // Здесь мы полагаем, что в .x файле содержится имя файла текстуры
                // (путь к ней тот же, что и к .x файлу)
                string textureFile = FilePath + materials[i].TextureFileName;
                try
                {
                    // Извлекаем информацию о текстуре
                    info = BaseTexture.GetImageInformationFromFile(textureFile);
                    //Console.WriteLine("Файл с текстурой:" + textureFile);
                    //Console.WriteLine(info);
                }
                catch
                {
                    Console.WriteLine("Текстура не найдена!");
                }
                switch (info.ResourceType)
                {
                    case ResourceType.Texture:
                        meshTextures[i] = new Texture(device, textureFile);
                        break;
                    case ResourceType.CubeTexture:
                        meshTextures[i] = new CubeTexture(device, textureFile);
                        break;
                    case ResourceType.VolumeTexture:
                        meshTextures[i] = new VolumeTexture(device, textureFile);
                        break;
                }
            }
        }
    }


    /// <summary> Обработка события OnResize() </summary>
    protected override void OnResize(EventArgs e)
    {
        if (this.WindowState == FormWindowState.Minimized)
        {
            return;
        }
        if (device != null)
        {
            if (!BuildPresentParameters())
            {
                throw new Exception("Устройство сбросить невозможно!");
            }
            font.OnLostDevice();//////////////////////////////////////////////////////////
            device.Reset(presentParams);
            
        }
        base.OnResize(e);
    }

    // Выбор режима отображения - сеточный (WireFrame) или сплошной (Solid)
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        if ((int)e.KeyChar == (int)Keys.Escape)
        {
            this.Close();
        }
        if ((e.KeyChar == 'w') || (e.KeyChar == 'ц')) { device.RenderState.FillMode = FillMode.WireFrame; }
        if ((e.KeyChar == 's') || (e.KeyChar == 'ы')) { device.RenderState.FillMode = FillMode.Solid; }
        base.OnKeyPress(e);
    }

}
Re: Вершинный и индексный буфферы.
От: Аноним  
Дата: 12.04.06 16:19
Оценка:
Предлагаю вашему вниманию еще несколько стандартных уроков
на демонстрацию буфферов.

//-----------------------------------------------------------------
// Вершинный буфер. Плоский треугольник.
//-----------------------------------------------------------------

using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.Generic;
using Microsoft.DirectX.Direct3D.CustomVertex;

class WindowsFormDemo : Form
{
    // Создаем устройство
    private Device device = null;
    // параметры представления
    PresentParameters presentParams = new PresentParameters();
    private GraphicsBuffer<PositionColored> vb;///////////////////////////////////

    /// <summary>
    /// конструктор
    /// </summary>
    public WindowsFormDemo()
    {
        this.Text = "Инициализация устройства DirectX";
        this.MinimumSize = new Size(50, 100);
        this.ClientSize = new Size(640, 480);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
    }
    /// <summary> Инициализация графического устройства </summary>
    public void InitializeGraphics()
    {
        if (BuildPresentParameters())
        {
            // Инициализация устройства.
            device = new Device(0, DeviceType.Hardware, this.Handle,
                CreateFlags.SoftwareVertexProcessing, presentParams);
        }
        else
        {
            Console.WriteLine("Устройство не построено!");
            return;
        }

        vb = new GraphicsBuffer<PositionColored>(3);/////////////////////////////////
        vb.Write(new PositionColored(-2.0f, -2.0f, 5.0f, Color.Red));////////////////
        vb.Write(new PositionColored(0.0f, 2.0f, 5.0f, Color.Green));////////////////
        vb.Write(new PositionColored(2.0f, -2.0f, 5.0f, Color.Blue));////////////////
    }

    /// <summary> Задаем параметры представления. </summary>
    public bool BuildPresentParameters()
    {
        presentParams = new PresentParameters();
        presentParams.SwapEffect = SwapEffect.Discard;
        presentParams.IsWindowed = true;
        presentParams.EnableAutoDepthStencil = true;
        presentParams.AutoDepthStencilFormat = DepthFormat.D16;

        return true;
    }
    /// <summary> Строим камеру. </summary>
    private void SetupCamera()
    {
        // Параметры камеры
        device.Transform.Projection =
            Matrix.PerspectiveFieldOfViewLeftHanded((float)Math.PI / 4,
            (float)this.Width / this.Height, 1.0f, 100.0f);

        // Выключаем освещение
        device.RenderState.Lighting = false;////////////////////////////////
        //Режим отбора и устранения(исключени невидимой поверхности)
        device.RenderState.CullMode = Cull.None;

    }
    /// <summary> Точка входа в приложение </summary>
    public static void Main()
    {
        using (WindowsFormDemo frm = new WindowsFormDemo())
        {
            try
            {
                frm.InitializeGraphics(); // Инициализация графического устройства
            }
            catch
            {
                MessageBox.Show("Инициализация DirectX не выполнена!");
            }
            Application.Run(frm);
        }
    }

    /// <summary> Обработка события Paint </summary>
    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
    {
        device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,    // что именно хотим очистить (текущее окно) 
                     System.Drawing.Color.Black, // цвет очистки
                     1.0f, // буфер глубины.
                     0);
        SetupCamera();  //  Установка камеры

        device.BeginScene();

        device.VertexFormat = PositionColored.Format;//////////////////////////////////////////
        device.DrawUserPrimitives(PrimitiveType.TriangleList, 1, vb);//////////////////////////

        device.EndScene();
        device.Present();
        this.Invalidate();
    }

    /// <summary> Обработка события OnResize() </summary>
    protected override void OnResize(EventArgs e)
    {
        if (this.WindowState == FormWindowState.Minimized)
        {
            return;
        }
        if (device != null)
        {
            if (!BuildPresentParameters())
            {
                throw new Exception("Устройство сбросить невозможно!");
            }
            device.Reset(presentParams);
        }
        base.OnResize(e);
    }

}
Re[2]: Вершинный и индексный буфферы.
От: mukhomor  
Дата: 12.04.06 16:23
Оценка:
//-----------------------------------------------------------------
// Вершинный буфер. Пример куба.
//-----------------------------------------------------------------

/* Небольшое изменение в процедуре заполнения буффера */


using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.Generic;
using Microsoft.DirectX.Direct3D.CustomVertex;

class WindowsFormDemo : Form
{
    // Создаем устройство
    private Device device = null;
    // параметры представления
    PresentParameters presentParams = new PresentParameters();
    private VertexBuffer vb;///////////////////////////////////
    float angle = 0.0f;

    /// <summary>
    /// конструктор
    /// </summary>
    public WindowsFormDemo()
    {
        this.Text = "Инициализация устройства DirectX";
        this.MinimumSize = new Size(50, 100);
        this.ClientSize = new Size(640, 480);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
    }
    /// <summary> Инициализация графического устройства </summary>
    public void InitializeGraphics()
    {
        if (BuildPresentParameters())
        {
            // Инициализация устройства.
            device = new Device(0, DeviceType.Hardware, this.Handle,
                CreateFlags.SoftwareVertexProcessing, presentParams);
        }
        else
        {
            Console.WriteLine("Устройство не построено!");
            return;
        }


        // Вершинный буфер из 36 вершин/////////////////////////////////////
        vb = new VertexBuffer(device, /////////////////////////////////////
            36 * PositionColored.StrideSize, /////  36 !!
            Usage.WriteOnly,
            PositionColored.Format,
            Pool.Managed,
            null);
        vb.Created += new EventHandler(vb_Created);/////////////////////////
        vb_Created(vb, null);///////////////////////////////////////////////

    }

    // заполняем буффер данными
    void vb_Created(object sender, EventArgs e)
    {
        GraphicsBuffer<PositionColored> verts = vb.Lock<PositionColored>(0, 0, LockFlags.None);
        // лицевая поверхность
        verts[0] = new PositionColored(-1.0f, 1.0f, 1.0f, Color.Red.ToArgb());
        verts[1] = new PositionColored(-1.0f, -1.0f, 1.0f, Color.Red.ToArgb());
        verts[2] = new PositionColored(1.0f, 1.0f, 1.0f, Color.Red.ToArgb());
        verts[3] = new PositionColored(-1.0f, -1.0f, 1.0f, Color.Red.ToArgb());
        verts[4] = new PositionColored(1.0f, -1.0f, 1.0f, Color.Red.ToArgb());
        verts[5] = new PositionColored(1.0f, 1.0f, 1.0f, Color.Red.ToArgb());

        // задняя поверхность
        verts[6] = new PositionColored(-1.0f, 1.0f, -1.0f, Color.Blue.ToArgb());
        verts[7] = new PositionColored(1.0f, 1.0f, -1.0f, Color.Blue.ToArgb());
        verts[8] = new PositionColored(-1.0f, -1.0f, -1.0f, Color.Blue.ToArgb());
        verts[9] = new PositionColored(-1.0f, -1.0f, -1.0f, Color.Blue.ToArgb());
        verts[10] = new PositionColored(1.0f, 1.0f, -1.0f, Color.Blue.ToArgb());
        verts[11] = new PositionColored(1.0f, -1.0f, -1.0f, Color.Blue.ToArgb());

        // верхняя грань
        verts[12] = new PositionColored(-1.0f, 1.0f, 1.0f, Color.Yellow.ToArgb());
        verts[13] = new PositionColored(1.0f, 1.0f, -1.0f, Color.Yellow.ToArgb());
        verts[14] = new PositionColored(-1.0f, 1.0f, -1.0f, Color.Yellow.ToArgb());
        verts[15] = new PositionColored(-1.0f, 1.0f, 1.0f, Color.Yellow.ToArgb());
        verts[16] = new PositionColored(1.0f, 1.0f, 1.0f, Color.Yellow.ToArgb());
        verts[17] = new PositionColored(1.0f, 1.0f, -1.0f, Color.Yellow.ToArgb());

        // нижняя грань
        verts[18] = new PositionColored(-1.0f, -1.0f, 1.0f, Color.Black.ToArgb());
        verts[19] = new PositionColored(-1.0f, -1.0f, -1.0f, Color.Black.ToArgb());
        verts[20] = new PositionColored(1.0f, -1.0f, -1.0f, Color.Black.ToArgb());
        verts[21] = new PositionColored(-1.0f, -1.0f, 1.0f, Color.Black.ToArgb());
        verts[22] = new PositionColored(1.0f, -1.0f, -1.0f, Color.Black.ToArgb());
        verts[23] = new PositionColored(1.0f, -1.0f, 1.0f, Color.Black.ToArgb());

        // левая грань
        verts[24] = new PositionColored(-1.0f, 1.0f, 1.0f, Color.Gray.ToArgb());
        verts[25] = new PositionColored(-1.0f, -1.0f, -1.0f, Color.Gray.ToArgb());
        verts[26] = new PositionColored(-1.0f, -1.0f, 1.0f, Color.Gray.ToArgb());
        verts[27] = new PositionColored(-1.0f, 1.0f, -1.0f, Color.Gray.ToArgb());
        verts[28] = new PositionColored(-1.0f, -1.0f, -1.0f, Color.Gray.ToArgb());
        verts[29] = new PositionColored(-1.0f, 1.0f, 1.0f, Color.Gray.ToArgb());

        // правая грань
        verts[30] = new PositionColored(1.0f, 1.0f, 1.0f, Color.Green.ToArgb());
        verts[31] = new PositionColored(1.0f, -1.0f, 1.0f, Color.Green.ToArgb());
        verts[32] = new PositionColored(1.0f, -1.0f, -1.0f, Color.Green.ToArgb());
        verts[33] = new PositionColored(1.0f, 1.0f, -1.0f, Color.Green.ToArgb());
        verts[34] = new PositionColored(1.0f, 1.0f, 1.0f, Color.Green.ToArgb());
        verts[35] = new PositionColored(1.0f, -1.0f, -1.0f, Color.Green.ToArgb());
 
        vb.Unlock();//////////////////////////////////
        verts.Dispose();
    }


    /// <summary> Задаем параметры представления. </summary>
    public bool BuildPresentParameters()
    {
        presentParams = new PresentParameters();
        presentParams.SwapEffect = SwapEffect.Discard;
        presentParams.IsWindowed = true;
        presentParams.EnableAutoDepthStencil = true;
        presentParams.AutoDepthStencilFormat = DepthFormat.D16;

        return true;
    }
    /// <summary> Строим камеру. </summary>
    private void SetupCamera()
    {
        // Параметры камеры
        device.Transform.Projection =
            Matrix.PerspectiveFieldOfViewLeftHanded((float)Math.PI / 4,
            (float)this.Width / (float)this.Height, 1.0f, 100.0f);
        // Установка камеры
        device.Transform.View =
            Matrix.LookAtLeftHanded(new Vector3(0, 0, 5.0f),
            new Vector3(),
            new Vector3(0, 1, 0));
        device.Transform.World = Matrix.RotationY(angle / (float)Math.PI * 4.0f)*
            Matrix.RotationZ(angle / (float)Math.PI * 4.0f)*
            Matrix.RotationX(angle / (float)Math.PI * 4.0f);

        // Отключаем освещение
        device.RenderState.Lighting = false;
        //Режим отбора и устранения(исключени невидимой поверхности)
        device.RenderState.CullMode = Cull.None;

    }
    /// <summary> Точка входа в приложение </summary>
    public static void Main()
    {
        using (WindowsFormDemo frm = new WindowsFormDemo())
        {
            try
            {
                frm.InitializeGraphics(); // Инициализация графического устройства
            }
            catch
            {
                MessageBox.Show("Инициализация DirectX не выполнена!");
            }
            Application.Run(frm);
        }
    }

    /// <summary> Обработка события Paint </summary>
    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
    {
        device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,    // что именно хотим очистить (текущее окно) 
                     System.Drawing.Color.Brown, // цвет очистки
                     1.0f, // буфер глубины.
                     0);
        SetupCamera();  //  Установка камеры
        angle += 0.02f;

        device.BeginScene();

        device.VertexFormat = PositionColored.Format;/////////////////////////////////////
        device.SetStreamSource(0, vb, 0, PositionColored.StrideSize);//////////////////
        device.DrawPrimitives(PrimitiveType.TriangleList, 0, 12);/////////// 12! ///////////////

        device.EndScene();
        device.Present();
        this.Invalidate();
    }

    /// <summary> Обработка события OnResize() </summary>
    protected override void OnResize(EventArgs e)
    {
        if (this.WindowState == FormWindowState.Minimized)
        {
            return;
        }
        if (device != null)
        {
            if (!BuildPresentParameters())
            {
                throw new Exception("Устройство сбросить невозможно!");
            }
            device.Reset(presentParams);
        }
        base.OnResize(e);
    }

}
Re[2]: Вершинный и индексный буфферы.
От: mukhomor  
Дата: 12.04.06 16:24
Оценка:
//-----------------------------------------------------------------
// Индексный буфер. Пример икосаэдра.
//-----------------------------------------------------------------

/* Простой пример икосаэдра и куба.*/


using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.Generic;
using Microsoft.DirectX.Direct3D.CustomVertex;

class WindowsFormDemo : Form
{
    // Создаем устройство
    private Device device = null;
    // параметры представления
    PresentParameters presentParams = new PresentParameters();
    float angle = 0.0f;

    /// <summary>
    /// конструктор
    /// </summary>
    public WindowsFormDemo()
    {
        this.Text = "Инициализация устройства DirectX";
        this.MinimumSize = new Size(50, 100);
        this.ClientSize = new Size(640, 480);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
    }
    /// <summary> Инициализация графического устройства </summary>
    public void InitializeGraphics()
    {
        if (BuildPresentParameters())
        {
            // Инициализация устройства.
            device = new Device(0, DeviceType.Hardware, this.Handle,
                CreateFlags.SoftwareVertexProcessing, presentParams);
        }
        else
        {
            Console.WriteLine("Устройство не построено!");
            return;
        }

    }
    
    /// <summary> Задаем параметры представления. </summary>
    public bool BuildPresentParameters()
    {
        presentParams = new PresentParameters();
        presentParams.SwapEffect = SwapEffect.Discard;
        presentParams.IsWindowed = true;
        presentParams.EnableAutoDepthStencil = true;
        presentParams.AutoDepthStencilFormat = DepthFormat.D16;

        return true;
    }
    /// <summary> Строим камеру. </summary>
    private void SetupCamera()
    {
        // Параметры камеры
        device.Transform.Projection =
            Matrix.PerspectiveFieldOfViewLeftHanded((float)Math.PI / 4,
            (float)this.Width / (float)this.Height, 1.0f, 100.0f);
        // Установка камеры
        device.Transform.View =
            Matrix.LookAtLeftHanded(new Vector3(0, 0, 10.0f),
            new Vector3(),
            new Vector3(0, 1, 0));
        

        // Отключаем освещение
        device.RenderState.Lighting = false;
        //Режим отбора и устранения(исключени невидимой поверхности)
        device.RenderState.CullMode = Cull.None;

    }
    /// <summary> Точка входа в приложение </summary>
    public static void Main()
    {
        using (WindowsFormDemo frm = new WindowsFormDemo())
        {
            try
            {
                frm.InitializeGraphics(); // Инициализация графического устройства
            }
            catch
            {
                MessageBox.Show("Инициализация DirectX не выполнена!");
            }
            Application.Run(frm);
        }
    }

    /// <summary> Обработка события Paint </summary>
    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
    {
        device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,    // что именно хотим очистить (текущее окно) 
                     System.Drawing.Color.Black, // цвет очистки
                     1.0f, // буфер глубины.
                     0);
        SetupCamera();  //  Установка камеры
        angle += 0.04f;

        device.BeginScene();

        DrawCube(device);
        Drawicosahedron(device);

        device.EndScene();
        device.Present();
        this.Invalidate();
    }

    /// <summary> Обработка события OnResize() </summary>
    protected override void OnResize(EventArgs e)
    {
        if (this.WindowState == FormWindowState.Minimized)
        {
            return;
        }
        if (device != null)
        {
            if (!BuildPresentParameters())
            {
                throw new Exception("Устройство сбросить невозможно!");
            }
            device.Reset(presentParams);
        }
        base.OnResize(e);
    }

    private void DrawCube(Device device)
    {
        device.Transform.World = Matrix.RotationYawPitchRoll(angle*3 / (float)Math.PI,
            angle / (float)Math.PI / 3.0f,
            angle / (float)Math.PI);
        short[] indices = 
                          {0,1,2, 
                           1,3,2, 
                           4,5,6, 
                           6,5,7,
                           0,5,4, 
                           0,2,5, 
                           1,6,7,
                           1,7,3, 
                           0,6,1, 
                           4,6,0, 
                           2,3,7, 
                           5,2,7 };
         VertexBuffer vb = null;
         IndexBuffer ib = null;
         // Вершинный буфер из 8 вершин
         vb = new VertexBuffer(device, 
             8 * PositionColored.StrideSize, /////  8 !!
             Usage.WriteOnly,
             PositionColored.Format,
             Pool.Managed,
             null);
         // Индексный буффер          
         ib = new IndexBuffer(device, 
             36 * sizeof(ushort), /////  36 !!
             Usage.WriteOnly,
             Pool.Managed,
             true,
             null);
         GraphicsBuffer<PositionColored> vertex = vb.Lock<PositionColored>(0, 0, LockFlags.None);
         vertex[0] = new PositionColored(-1.0f, 1.0f, 1.0f, Color.Red.ToArgb());
         vertex[1] = new PositionColored(-1.0f, -1.0f, 1.0f, Color.Purple.ToArgb());
         vertex[2] = new PositionColored(1.0f, 1.0f, 1.0f, Color.Olive.ToArgb());
         vertex[3] = new PositionColored(1.0f, -1.0f, 1.0f, Color.Blue.ToArgb());
         vertex[4] = new PositionColored(-1.0f, 1.0f, -1.0f, Color.RoyalBlue.ToArgb());
         vertex[5] = new PositionColored(1.0f, 1.0f, -1.0f, Color.LemonChiffon.ToArgb());
         vertex[6] = new PositionColored(-1.0f, -1.0f, -1.0f, Color.DarkMagenta.ToArgb());
         vertex[7] = new PositionColored(1.0f, -1.0f, -1.0f, Color.Transparent.ToArgb());
         vb.Unlock();
         vertex.Dispose();

         GraphicsBuffer<short> vertex_ind = ib.Lock<short>(0, 0, LockFlags.None);
         // лицевая поверхность
         vertex_ind.Write(indices);

         ib.Unlock();
         vertex.Dispose();

         device.VertexFormat = PositionColored.Format; ///////////////////!!!///////////////////
         // Отображение содержимого буфера на экране////////////////////////////////////////////
         device.SetStreamSource(0, vb, 0, PositionColored.StrideSize);//////////////////////////
         device.Indices = ib;///////////////////////////////////////////////////////////////////
         device.DrawIndexedPrimitives(PrimitiveType.TriangleList, // тип примитива /////////////
             0,           //  смещение от начала индексного буфера до первого индекса вершины
             0,           //  минимальный индекс вершины в этом вызове
             8,           // число вершин, используемых в этом вызове
             0,           // местоположение в массиве для запуска считывания данных о вершине
             indices.Length / 3);  // число отображаемых примитивов     

    }

    private void Drawicosahedron(Device device)
    {
        device.Transform.World = 
            Matrix.RotationYawPitchRoll(angle / (float)Math.PI,
            angle / (float)Math.PI / 2.0f,
            angle / (float)Math.PI) *Matrix.Translation(2.5f, 0f, 3.0f)*
            Matrix.RotationY(angle / (float)Math.PI);

        short[] indices = 
          {1,4,0, 
           4,9,0, 
           4,5,9, 
           8,5,4,
           1,8,4, 
           1,10,8, 
           10,3,8,
           8,3,5, 
           3,2,5,
           3,7,2,
           3,10,7,
           10,6,7,
           6,11,7,
           6,0,11,
           6,1,0,
           10,1,6,
           11,0,9,
           2,11,9,
           5,2,9,
           11,2,7};

        VertexBuffer vb = null;
        IndexBuffer ib = null;
        // Вершинный буфер из 8 вершин
        vb = new VertexBuffer(device,
            20 * PositionColored.StrideSize, /////  20 !!
            Usage.WriteOnly,
            PositionColored.Format,
            Pool.Managed,
            null);
        // Индексный буффер          
        ib = new IndexBuffer(device,
            60 * sizeof(ushort), /////  60 !!
            Usage.WriteOnly,
            Pool.Managed,
            true,
            null);
        GraphicsBuffer<PositionColored> verts = vb.Lock<PositionColored>(0, 0, LockFlags.None);
        float x = 0.525731112119133606f;
        float z = 0.850650808352039932f;

        verts[0] = new PositionColored(-x, 0.0f, z, Color.Red.ToArgb());
        verts[1] = new PositionColored(x, 0.0f, z, Color.Purple.ToArgb());
        verts[2] = new PositionColored(-x, 0.0f, -z, Color.Olive.ToArgb());
        verts[3] = new PositionColored(x, 0.0f, -z, Color.Blue.ToArgb());
        verts[4] = new PositionColored(0.0f, z, x, Color.RoyalBlue.ToArgb());
        verts[5] = new PositionColored(0.0f, z, -x, Color.LemonChiffon.ToArgb());
        verts[6] = new PositionColored(0.0f, -z, x, Color.DarkMagenta.ToArgb());
        verts[7] = new PositionColored(0.0f, -z, -x, Color.Transparent.ToArgb());
        verts[8] = new PositionColored(z, x, 0.0f, Color.Transparent.ToArgb());
        verts[9] = new PositionColored(-z, x, 0.0f, Color.Transparent.ToArgb());
        verts[10] = new PositionColored(z, -x, 0.0f, Color.Transparent.ToArgb());
        verts[11] = new PositionColored(-z, -x, 0.0f, Color.Transparent.ToArgb());

        vb.Unlock();
        verts.Dispose();

        GraphicsBuffer<short> vertex_ind = ib.Lock<short>(0, 0, LockFlags.None);
        // лицевая поверхность
        vertex_ind.Write(indices);

        ib.Unlock();
        vertex_ind.Dispose();

        device.VertexFormat = PositionColored.Format; ///////////////////!!!///////////////////
        // Отображение содержимого буфера на экране////////////////////////////////////////////
        device.SetStreamSource(0, vb, 0, PositionColored.StrideSize);//////////////////////////
        device.Indices = ib;///////////////////////////////////////////////////////////////////
        device.DrawIndexedPrimitives(PrimitiveType.TriangleList, // тип примитива /////////////
            0,           //  смещение от начала индексного буфера до первого индекса вершины
            0,           //  минимальный индекс вершины в этом вызове
            20,           // число вершин, используемых в этом вызове
            0,           // местоположение в массиве для запуска считывания данных о вершине
            indices.Length / 3);  // число отображаемых примитивов     
    }

}
Re[2]: Managed DirectX на C#. Туториалы.
От: mukhomor  
Дата: 12.04.06 16:29
Оценка:
Огромное количество материала о Managed DirectX можно найти тут:
http://www.thezbuffer.com/

Здесь же имеется немалое количество ссылок на туториалы.
Re: Managed DirectX на C#. Туториалы.
От: Alex57  
Дата: 13.04.06 05:36
Оценка:
Здравствуйте, mukhomor, Вы писали:

Такое ощущение, что Managed DirectX закончился и начался XNA.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.