sábado, junio 18, 2005
Un poquito de código...
Hola,
Como prometí hace una eternidad, vamos a ver el hola mundo de DirectX. Es decir, un triángulo coloreado en pantalla. Pero en vaz de mostrarlo a pantalla completa, como en el típico ejemplo, vamos a verlo dibujado sobre un control de tipo Panel.
Por lo tanto, suponemos que tenemos un formulario windows, con un panel llamado pnlBack, que es donde vamos a renderizar nuestro triángulo.
El código es el siguiente:
// Hemos de añadir los siguientes using:
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
// Y las variables:
protected Device device = null;
protected VertexBuffer vbVerts = null;
private float fAngle = 0.0f;
// Esta función se encarga de inicializar los gráficos.
public bool InitializeGraphics()
{
try
{
// Inicializamos Direct3D
PresentParameters presentParams = new PresentParameters();
// Le indicamos que tiene que pintar en una ventana.
presentParams.Windowed = true;
// Le indicamos que deseche los cambios entre frames.
presentParams.SwapEffect = SwapEffect.Discard;
// Creamos el dispositivo de renderizado, indicándole
// que utilice aceleración por hardware, que renderice
// sobre el panel, y que los vértices se generan por software.
device = new Device(0, DeviceType.Hardware, this.pnlBack,
CreateFlags.SoftwareVertexProcessing, presentParams);
// Creamos un buffer de vértices, con 3 vértices. Sólo escritura.
// El formato de vértice es coloreado y con datos de posición.
vbVerts = new VertexBuffer(typeof(CustomVertex.PositionColored), 3, device,
Usage.WriteOnly | Usage.Dynamic,
CustomVertex.PositionColored.Format,
Pool.Default);
// Inicializamos los vértices:
CustomVertex.PositionColored[] aVerts = new CustomVertex.PositionColored[3];
aVerts[0].Color = Color.Red.ToArgb();
aVerts[0].X = 0.5f;
aVerts[0].Y = 0.0f;
aVerts[0].Z = 0;
aVerts[1].Color = Color.Green.ToArgb();
aVerts[1].X = -0.5f;
aVerts[1].Y = 0;
aVerts[1].Z = 0;
aVerts[2].Color = Color.Blue.ToArgb();
aVerts[2].X = 0;
aVerts[2].Y = 0.5f;
aVerts[2].Z = 0;
// Los copiamos en el buffer de vértices (para que su dibujado sea
// más rápido.
GraphicsStream gs ;
gs = vbVerts.Lock(0, 0, LockFlags.None);
gs.Write(aVerts);
vbVerts.Unlock();
// Establecemos el formato de vértice en el dispositivo.
device.VertexFormat = CustomVertex.PositionColored.Format;
// Cargamos el buffer de vértices en el dispositivo.
device.SetStreamSource(0, vbVerts, 0,
CustomVertex.PositionColored.StrideSize);
// Deshabilitamos la iluminación, así nos evitamos tener que crear
// luces, y que nos aparezca el triángulo coloreado. Si no lo hacemos,
// al no haber declarado luces, el triángulo aparecería negro.
device.RenderState.Lighting = false;
return true;
}
catch (DirectXException)
{
return false;
}
}
///
/// Movemos la escena.
///
protected virtual void FrameMove()
{
// Rotamos la vista sobre el eje Z. Si rotásemos sobre cualquier
// otro eje, al cabo de un rato nos desaparecería el triángulo (o
// parte de él) debido al orden de los vértices.
Matrix mRotar = Matrix.Identity;
mRotar.RotateZ(fAngle);
fAngle += 0.01f;
device.SetTransform(TransformType.View, mRotar);
}
///
/// Pintamos la escena.
///
protected virtual void Render()
{
if (device != null)
{
// Pintamos el fondo negro.
device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
device.BeginScene();
// Pintamos el triángulo a partir de los trés vértices del buffer.
device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 3);
device.EndScene();
device.Present();
}
}
///
/// Bucle principal.
///
public void Run()
{
// Mientras el formulario sea válido, renderizamos y procesamos
// los mensajes de windows.
while (this.Created)
{
FrameMove();
Render();
Application.DoEvents();
}
}
// Gestión del evento OnPaint.
protected override void OnPaint(PaintEventArgs e)
{
this.Render();
}
// Cerramos al pulsar ESC.
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
if ((int)e.KeyChar == (int)System.Windows.Forms.Keys.Escape)
{
this.Close();
}
}
///
/// Aquí es donde comienza la ejecución:
///
static void Main()
{
using (Form1 frmMain = new Form1())
{
// Inicializamos DirectX
if (!frmMain.InitializeGraphics())
{
MessageBox.Show("Error while initializing Direct3D");
return;
}
frmMain.Show();
// A Correr!!!
frmMain.Run();
}
}
Bueno, y eso es todo por hoy... Nos vemos!
Como prometí hace una eternidad, vamos a ver el hola mundo de DirectX. Es decir, un triángulo coloreado en pantalla. Pero en vaz de mostrarlo a pantalla completa, como en el típico ejemplo, vamos a verlo dibujado sobre un control de tipo Panel.
Por lo tanto, suponemos que tenemos un formulario windows, con un panel llamado pnlBack, que es donde vamos a renderizar nuestro triángulo.
El código es el siguiente:
// Hemos de añadir los siguientes using:
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
// Y las variables:
protected Device device = null;
protected VertexBuffer vbVerts = null;
private float fAngle = 0.0f;
// Esta función se encarga de inicializar los gráficos.
public bool InitializeGraphics()
{
try
{
// Inicializamos Direct3D
PresentParameters presentParams = new PresentParameters();
// Le indicamos que tiene que pintar en una ventana.
presentParams.Windowed = true;
// Le indicamos que deseche los cambios entre frames.
presentParams.SwapEffect = SwapEffect.Discard;
// Creamos el dispositivo de renderizado, indicándole
// que utilice aceleración por hardware, que renderice
// sobre el panel, y que los vértices se generan por software.
device = new Device(0, DeviceType.Hardware, this.pnlBack,
CreateFlags.SoftwareVertexProcessing, presentParams);
// Creamos un buffer de vértices, con 3 vértices. Sólo escritura.
// El formato de vértice es coloreado y con datos de posición.
vbVerts = new VertexBuffer(typeof(CustomVertex.PositionColored), 3, device,
Usage.WriteOnly | Usage.Dynamic,
CustomVertex.PositionColored.Format,
Pool.Default);
// Inicializamos los vértices:
CustomVertex.PositionColored[] aVerts = new CustomVertex.PositionColored[3];
aVerts[0].Color = Color.Red.ToArgb();
aVerts[0].X = 0.5f;
aVerts[0].Y = 0.0f;
aVerts[0].Z = 0;
aVerts[1].Color = Color.Green.ToArgb();
aVerts[1].X = -0.5f;
aVerts[1].Y = 0;
aVerts[1].Z = 0;
aVerts[2].Color = Color.Blue.ToArgb();
aVerts[2].X = 0;
aVerts[2].Y = 0.5f;
aVerts[2].Z = 0;
// Los copiamos en el buffer de vértices (para que su dibujado sea
// más rápido.
GraphicsStream gs ;
gs = vbVerts.Lock(0, 0, LockFlags.None);
gs.Write(aVerts);
vbVerts.Unlock();
// Establecemos el formato de vértice en el dispositivo.
device.VertexFormat = CustomVertex.PositionColored.Format;
// Cargamos el buffer de vértices en el dispositivo.
device.SetStreamSource(0, vbVerts, 0,
CustomVertex.PositionColored.StrideSize);
// Deshabilitamos la iluminación, así nos evitamos tener que crear
// luces, y que nos aparezca el triángulo coloreado. Si no lo hacemos,
// al no haber declarado luces, el triángulo aparecería negro.
device.RenderState.Lighting = false;
return true;
}
catch (DirectXException)
{
return false;
}
}
///
/// Movemos la escena.
///
protected virtual void FrameMove()
{
// Rotamos la vista sobre el eje Z. Si rotásemos sobre cualquier
// otro eje, al cabo de un rato nos desaparecería el triángulo (o
// parte de él) debido al orden de los vértices.
Matrix mRotar = Matrix.Identity;
mRotar.RotateZ(fAngle);
fAngle += 0.01f;
device.SetTransform(TransformType.View, mRotar);
}
///
/// Pintamos la escena.
///
protected virtual void Render()
{
if (device != null)
{
// Pintamos el fondo negro.
device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
device.BeginScene();
// Pintamos el triángulo a partir de los trés vértices del buffer.
device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 3);
device.EndScene();
device.Present();
}
}
///
/// Bucle principal.
///
public void Run()
{
// Mientras el formulario sea válido, renderizamos y procesamos
// los mensajes de windows.
while (this.Created)
{
FrameMove();
Render();
Application.DoEvents();
}
}
// Gestión del evento OnPaint.
protected override void OnPaint(PaintEventArgs e)
{
this.Render();
}
// Cerramos al pulsar ESC.
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
if ((int)e.KeyChar == (int)System.Windows.Forms.Keys.Escape)
{
this.Close();
}
}
///
/// Aquí es donde comienza la ejecución:
///
static void Main()
{
using (Form1 frmMain = new Form1())
{
// Inicializamos DirectX
if (!frmMain.InitializeGraphics())
{
MessageBox.Show("Error while initializing Direct3D");
return;
}
frmMain.Show();
// A Correr!!!
frmMain.Run();
}
}
Bueno, y eso es todo por hoy... Nos vemos!
Comments:
<< Home
¡ Cojonudo el ejemplo !
Un par de comentarios:
1. El panel que hay que poner en el form, se tiene que llamar pnlBack y no pnlRender, para que compile ;-)
2. Por lo menos en mi explorer, hay una linea de código que no compila:
vbVerts = new VertexBuffer(typeof(CustomVertex.PositionColored), 3, device,
Usage.WriteOnly Usage.Dynamic,
CustomVertex.PositionColored.Format, Pool.Default);
Justo entre "Usage.WriteOnly" y "Usage.Dynamic", le he puesto una barra vertical (la | del 1 en los teclados)... supongo que es correcto porque el ejemplo chuta, pero que me corrija el autor ;-)
Un par de comentarios:
1. El panel que hay que poner en el form, se tiene que llamar pnlBack y no pnlRender, para que compile ;-)
2. Por lo menos en mi explorer, hay una linea de código que no compila:
vbVerts = new VertexBuffer(typeof(CustomVertex.PositionColored), 3, device,
Usage.WriteOnly Usage.Dynamic,
CustomVertex.PositionColored.Format, Pool.Default);
Justo entre "Usage.WriteOnly" y "Usage.Dynamic", le he puesto una barra vertical (la | del 1 en los teclados)... supongo que es correcto porque el ejemplo chuta, pero que me corrija el autor ;-)
Lo del pnlBack, un despiste. Eso me pasa por tener dos VS abiertos a la vez... ;)
Y lo de la barra del 1, totalmente cierto...
Eso me pasa por usar el editor de texto en vez del editor HTML directamente. Se me comió todos los espacios, y luego se me cepilló la barra vertical.
La próxima vez lo edito directamente en html y le meto un tag XMP para que muestre el código correctamente ;)
Muchas gracias!
Publicar un comentario
Y lo de la barra del 1, totalmente cierto...
Eso me pasa por usar el editor de texto en vez del editor HTML directamente. Se me comió todos los espacios, y luego se me cepilló la barra vertical.
La próxima vez lo edito directamente en html y le meto un tag XMP para que muestre el código correctamente ;)
Muchas gracias!
<< Home