2010. február 28., vasárnap

Managed DirectX - Geometriai primitívek

Most amikor már a DirectX 11-es kiadásánál tartunk el lehet azon gondolkodni, hogy van e értelme a DirectX 9-es verziójával foglalkozni. Az biztos, hogy az Xbox360 konzol még jó ideig csak ezt fogja támogatni és sok helyen még mindig az XP operációs rendszer van, ezért legalább egy D3D9 rendert mindenképpen érdemes implementálni a rendszerhez. Kezdésnek is talán picivel egyszerűbb a DX9, mert nem kell rögtön a shader programozást is megtanulni egy egyszerű háromszög kirajzolásához. Ezért én úgy gondolom, hogy mindenképpen érdemes a D3D9-el megismerkedni.
Az előző leckében létrehoztuk első háromszögünket. Most újra nekiindulunk és megismerkednünk a többi geometriai primitívvel is és a lehető legegyszerűbben hozzuk létre a DX Device-t.

Geometriai primitívek

Látványos grafikai képek készítéséhez meg kell ismerkednünk az alapvető háromdimenziós grafikai primitívekkel, amik elérhetőek a DX-en belül. A Direct3D-ben hatféle primitívet használhatunk.
  1. PointList – különálló pontok halmaza. A megadott vertexek különálló pontként jelenik meg, anélkül, hogy szakaszokkal összekötnénk őket.
  2. LineList – különálló szakaszok. A vertexek a megadott sorrend alapján, páronként szakaszokat alkotnak, ezért páros számú vertex megadása szükséges.
  3. LineStrip – szakaszsorozat. Hasonló a LineList-hez, azzal a különbséggel, hogy sorban összeköti az összes pontot, tetszőleges hosszúságú szakaszsorozatot előállítva. Az első vertex adja az első szakasz kezdőpontját a második vertex a végpontját és egyben a következő szakasz kezdőpontját – és így tovább.
  4. TriangleList – különálló háromszögek. A megadott vertexek sorrendben és hármas csoportokban definiálnak egy-egy háromszöget. Lényeges a vertexek sorrendje, ugyanis az éppen érvényben lévő bejárási módszer függvényében meghatározza, hogy az adott háromszög látható-e vagy sem.
  5. TriangleStrip – háromszögek sorozata közös oldallal. Az első három vertex adja az első háromszöget, és minden további vertex egy további háromszöget definiál, amelynek két vertexe az előző háromszögből származik.
  6. TriangleFan – legyező háromszögek. A háromszögek legyezőszerű elrendezése, amelyben minden háromszög egy közös csúcsponton osztozik.
A leírtakat jól szemlélteti a lenti ábra:

DirectX primitívek

A következő példaprogram a DX primitíveket mutatja be. A Form-on elhelyezünk egy Panelt, a DirectX a panelra fog rajzolni. Majd egy ComboBox segítségével tudunk majd váltani a primitívek között:
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace MDX_Rendering_Primitives
{
public partial class MainForm : Form
{
private Panel panel = null;
private Device device = null;
private ComboBox comboBox = null;

public MainForm()
{
InitializeComponent();
{
this.ClientSize = new Size(800, 600);
this.Text = "MDX - Rendering Primitives";
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
this.Focus();
}

comboBox.SelectedIndex = 2;
InitDevice();
}

private void InitDevice()
{
PresentParameters presentParams = new PresentParameters()
{
Windowed = true,
SwapEffect = SwapEffect.Flip
};

device = new Device(0, DeviceType.Hardware, panel.Handle, CreateFlags.SoftwareVertexProcessing, presentParams);
}
A Form és a DX device létrehozása után írjuk meg az OnPaint metódust:
        protected override void OnPaint(PaintEventArgs e)
{
CustomVertex.TransformedColored[] vertexes = new CustomVertex.TransformedColored[6];
CustomVertex.TransformedColored[] tempvert = new CustomVertex.TransformedColored[6];

vertexes[0].Position = new Vector4(100, 150, 0, 1.0f);
vertexes[0].Color = Color.Red.ToArgb();

vertexes[1].Position = new Vector4(50, 50, 0, 1.0f);
vertexes[1].Color = Color.Green.ToArgb();

vertexes[2].Position = new Vector4(100, 25, 0, 1.0f);
vertexes[2].Color = Color.Blue.ToArgb();

vertexes[3].Position = new Vector4(150, 50, 0, 1.0f);
vertexes[3].Color = Color.Yellow.ToArgb();

vertexes[4].Position = new Vector4(200, 100, 0, 1.0f);
vertexes[4].Color = Color.Red.ToArgb();

vertexes[5].Position = new Vector4(200, 200, 0, 1.0f);
vertexes[5].Color = Color.Green.ToArgb();

device.Clear(ClearFlags.Target, Color.Black.ToArgb(), 1.0f, 0);

device.BeginScene();
{
device.VertexFormat = CustomVertex.TransformedColored.Format;

switch (comboBox.SelectedIndex)
{
case 0: device.DrawUserPrimitives(PrimitiveType.LineList, 3, vertexes);
break;
case 1: device.DrawUserPrimitives(PrimitiveType.LineStrip, 5, vertexes);
break;
case 2:
{
device.RenderState.PointSize = 5.0f;
device.DrawUserPrimitives(PrimitiveType.PointList, 6, vertexes);
}
break;
case 3: device.DrawUserPrimitives(PrimitiveType.TriangleList, 2, vertexes);
break;
case 4:
{
tempvert[0] = vertexes[1];
tempvert[1] = vertexes[2];
tempvert[2] = vertexes[0];
tempvert[3] = vertexes[3];
tempvert[4] = vertexes[5];
tempvert[5] = vertexes[4];
device.DrawUserPrimitives(PrimitiveType.TriangleStrip, 6, tempvert);
}
break;
case 5: device.DrawUserPrimitives(PrimitiveType.TriangleFan, 4, vertexes);
break;
default:
break;
}
}
device.EndScene();
device.Present();
}
Az OnPaint() metódusban a következő ábrának megfelelő primitíveket készítjük el. A TriangleStrip esetében meg kell változtatni a vertexek sorrendjét:


Ha a ComboBox kiválasztott eleme megváltozik, akkor a Form újrarajzolását fogjuk kikényszeríteni:
        private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
{
Invalidate();
}
Ezzel el is készültünk:


A példa teljes forrása itt tekinthető meg:


Ha valamit kihagytam volna vagy valami nem érthető, semmi gond, legközelebb is innen folytatjuk.

0 megjegyzés :

Megjegyzés küldése