Google

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!

Comments:
¡ 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 ;-)
 
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!
 
Bueno, ya están corregidas ambas incidencias ;)
 
Publicar un comentario



<< Home

This page is powered by Blogger. Isn't yours?