XNA käytännössä korvaa Managed Direct X:n.
XNA on melko pieni paketti, jonka voi ladata täältä http://creators.xna.com/en-US/downloads
Tarvitset kuitenkin myös DirectX SDK:n ja Visual Studion tai Visual C# 2008 Express Edition.
Kolmio
Värillinen kolmio on melkein "Hello world" ohjelma, kun aloitetaan opiskelemaan 3d-grafiikkaohjelmointia. Tällä kertaa aionkin esitellä miten kolmio luodaan XNA:lla.
Käynnistä Visual C# ja luo uusi XNA projekti. XNA projekti on hämäävästi nimetty Windows Game ja XBox360 Game.

Tämä luo sinulle projektin, jossa on valmiiksi tehtynä pari perusjuttua peliä tehdessä, kuten ikkuna ja pääsilmukka. Nämä mm. ovat asioita, jotka teet aina likimain samalla tavalla. On siis varsin mukavaa, että XNA projekti tekee nämä valmiiksi.
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
#endregion
namespace BlogExample01
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
ContentManager content;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
content = new ContentManager(Services);
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadGraphicsContent(
bool loadAllContent)
{
if (loadAllContent)
{
}
}
protected override void UnloadGraphicsContent(
bool unloadAllContent)
{
if (unloadAllContent)
{
content.Unload();
}
}
protected override void Update(GameTime gameTime)
{
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
base.Draw(gameTime);
}
}
}
Jos käännät koodin saat eteesi ikkunan sinisellä pohjalla.
Haluamme kuitenkin sen kolmion ruudulle, joten meidän pitää kertoa millaisista pisteistä kolmio koostuu. Näitä pisteitä sanotaan vertekseiksi. XNA:ssa verteksit voivat sisältää paljonkin tietoa. Se mitä tietoa verteksillä on kerrotaan verteksiformaatissa. Näitä formaatteja voi tehdä itse tai käyttää XNA:n valmiita formaatteja, kuten tässä.
Käytämme verteksiformaattia VertexPositionColor, johon voidaan siis kirjoittaa paikka- ja väridata. Luodaan siis luokalle uusi member muuttuja (kaamea suomennos "jäsenmuuttuja") private VertexPositionColor[] m_vertices.
...
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
ContentManager content;
private VertexPositionColor[] m_vertices;
public Game1()
{
...
Seuraavaksi luodaan taulukkoon ne verteksit.
...
protected override void LoadGraphicsContent(
bool loadAllContent)
{
if (loadAllContent)
{
m_vertices = new VertexPositionColor[3];
m_vertices[0].Position = new Vector3(
-0.5f, -0.5f, 0f);
m_vertices[0].Color = Color.Red;
m_vertices[1].Position = new Vector3(
0, 0.5f, 0f);
m_vertices[1].Color = Color.Green;
m_vertices[2].Position = new Vector3(
0.5f, -0.5f, 0f);
m_vertices[2].Color = Color.Yellow;
}
}
...
Nyt meillä on verteksit, joilla voidaan piirtää kolmio, mutta näytönohjaimelle on kerrottava millaista vertexdataa on tulossa ja XNA:ssa se tehdään luomalla VertexDeclaration olio. VertexDeclaration tarvitsee myös pääsyn näytönohjaimeen, joka onnistuu XNA:n GraphicsDevice luokan kautta. Meidän pitää siis luoda oliot VertexDeclaration ja GraphicsDevice.
...
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager m_graphics;
ContentManager m_content;
GraphicsDevice m_device;
private VertexPositionColor[] m_vertices;
private VertexDeclaration m_vd;
public Game1()
{
...
...
protected override void LoadGraphicsContent(
bool loadAllContent)
{
if (loadAllContent)
{
m_device = m_graphics.GraphicsDevice;
m_vertices = new VertexPositionColor[3];
m_vertices[0].Position = new Vector3(
-0.5f, -0.5f, 0f);
m_vertices[0].Color = Color.Red;
m_vertices[1].Position = new Vector3(
0, 0.5f, 0f);
m_vertices[1].Color = Color.Green;
m_vertices[2].Position = new Vector3(
0.5f, -0.5f, 0f);
m_vertices[2].Color = Color.Yellow;
m_vd = new VertexDeclaration(m_device, VertexPositionColor.VertexElements);
...
Emme ole vieläkään valmiit piirtämään mitään :(, mutta olemme jo puolivälissä :).
XNA piirtää kaiken kaman ruudulle shaderien kautta. Eli meidän kirjoitettava Vertex- ja PixelShader voidaksemme piirtää jotain. Niiden kirjoittaminen on kuitenkin oma asiansa ja voimme tässä vaiheessa aivan hyvin tyytyä käyttämään jotain valmista shaderia ja murehtia niiden tekemisestä sitten joskus myöhemmin. Halutessasi voit lukea shadereistä lisää Direct X SDK:n dokuista tai vaikka Riemersin tutoriaaleista, joista meidän käyttämämme shader on otettu linkki. Tässä vaiheessa on kuitenkin tarpeen tietää miten shadereitä käytetään.
Shadereitä hallitaan Effect luokan kautta. Eli luomme Effect olion, johon ladataan HLSL tiedosto. Itse lataaminen suoritetaan Content luokan avulla, jonka XNA projekti on jo valmiiksi alustanut ohjelman käytettäväksi.
Shader tiedosto on normaali tekstitiedosto, jonka pääte tavallisesti on .fx. Tässä ohjeessa käytän simpleshader.fx shaderia. Se on äärimmäisen yksinkertainen shaderi, mutta se riittää meidän tarpeisiimme.
Lisää shader tiedosto projektiisi ja lataa shader Content luokan avulla käyttäen Visual C#:pin shaderille antamaa Asset Name nimeä. Se on yleensä tiedoston nimi ilman päätettä.
...
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager m_graphics;
ContentManager m_content;
GraphicsDevice m_device;
private Effect m_effect;
private VertexPositionColor[] m_vertices;
private VertexDeclaration m_vd;
...
...
protected override void LoadGraphicsContent(
bool loadAllContent)
{
if (loadAllContent)
{
m_device = m_graphics.GraphicsDevice;
m_effect = m_content.Load("simpleshader");
m_vertices = new VertexPositionColor[3];
...
Nyt meillä on kolmion verteksit, verteksiformaatti ja shaderi, jolla piirtää. Mitä vielä tarvitaan? Matriisi tai oikeastaan matriisit. Matriisi on taulukko numeroita, joiden selittäminen ei ole tässä juuri nyt tarpeen. Oikeastaan ne ovat melkoisen yksinkertaisia ja selkiintyvät kuin itsestään. Voimme kuitenkin käyttää niitä aivan hyvin vaikka emme niiden toimintaa ymmärtäisikään. Tarvitsemme kaksi matriisia. Näkymämatriisin ja projektiomatriisin. Yleensä tarvitaan matriiseja enemmänkin, mutta juuri nyt nuo kaksi riittävät. Näkymämatriisi on matriisi, joka kertoo XNA:lle missä ja missä asennossa katsojan silmä, eli kamera, on. Projektiomatriisi kertoo millainen kamera. Eli minkälainen FOV, lähi -ja kaukoleikkaus ja millainen aspect ratio näkymässä on.
Tarvitsemme kaksi uutta memberiä luokkaamme.
...
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager m_graphics;
ContentManager m_content;
GraphicsDevice m_device;
private Effect m_effect;
private VertexPositionColor[] m_vertices;
private VertexDeclaration m_vd;
private Matrix m_matView;
private Matrix m_matProj;
public Game1()
...
Ja asetamme näille asetukset, jotka sopivat ko. tilanteeseen.
...
protected override void LoadGraphicsContent(
bool loadAllContent)
{
if (loadAllContent)
{
m_device = m_graphics.GraphicsDevice;
m_effect = m_content.Load("simpleshader");
m_vertices = new VertexPositionColor[3];
m_vertices[0].Position = new Vector3(
-0.5f, -0.5f, 0f);
m_vertices[0].Color = Color.Red;
m_vertices[1].Position = new Vector3(
0, 0.5f, 0f);
m_vertices[1].Color = Color.Green;
m_vertices[2].Position = new Vector3(
0.5f, -0.5f, 0f);
m_vertices[2].Color = Color.Yellow;
m_vd = new VertexDeclaration(
m_device,
VertexPositionColor.VertexElements);
m_matView = Matrix.CreateLookAt(new Vector3(
0.0f, 0.0f, 2.0f),
new Vector3(0.0f, 0.0f, 0.0f),
new Vector3(0.0f, 1.0f, 0.0f));
m_matProj = Matrix.CreatePerspectiveFieldOfView(
MathHelper.PiOver4,
(float)m_device.Viewport.Width /
(float)m_device.Viewport.Height,
1.0f, 100.0f);
}
}
...
Ja lopultakin olemme valmiit piirtämään!
...
protected override void Draw(GameTime gameTime)
{
m_graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
m_device.RenderState.CullMode = CullMode.None;
m_device.RenderState.FillMode = FillMode.Solid;
...Asetetaan piilopintojen poisto pois päältä, jotta kolmio näkyy vaikka se olisi "väärin päin" ja asetetaan kolmion piirto fill moodiin. Eli kolmiot täytetään eikä piirretä niistä vain reunoja tai kärkipisteitä.Otetaan shaderista käyttöön Simplest tekniikka. Eli tämä on shaderiin kirjoitettu efekti, joka voi olla melkin mitä tahansa. Tällä kertaa se on hyvin yksinkertainen värien interpolointi verteksien välillä.
...
m_effect.CurrentTechnique = m_effect.Techniques["Simplest"];
m_effect.Parameters["xViewProjection"].SetValue(
m_matView * m_matProj);
m_effect.Begin();
...
Shader myös sisältää muuttujan, joka on xViewProjection matriisi. Sinun tulee antaa tämä matriisi jotta shader osaa projisoida verteksit oikein.
Koodi käy kaikki shaderin "passit" läpi. Tässä shaderissa passeja on vain yksi, mutta niitä voi olla enemmänkin.
...
foreach (EffectPass pass in
m_effect.CurrentTechnique.Passes)
{
pass.Begin();
...
Kerrotaan näyttökortille, millaista verteksidataa olemme lähettämässä. Lähetetään polygoni kortille ja lopuksi piirretään näyttökortin muistissa oleva data. Ja tulos näyttää tältä.
...
m_device.VertexDeclaration = m_vd;
m_device.DrawUserPrimitives(
PrimitiveType.TriangleList,
m_vertices, 0, 1);
pass.End();
}
m_effect.End();
base.Draw(gameTime);
}
...

Imuroi lähdekoodi






