Mostrando las entradas con la etiqueta XNA. Mostrar todas las entradas
Mostrando las entradas con la etiqueta XNA. Mostrar todas las entradas

SugarBlast!


Me di a la tarea de probar XNA 4 para Windows Phone Series 7, después de jugar un rato con él me gustaría compartir mis observaciones:

Fácil: Programar para WP7 es practicamente igual que porgamar un juego para PC, y el rendimiento que tiene en el simulador es bastante bueno, las caractarísitas de un juego de computadora están ahí, y los equipos que hay hasta el momento permiten tener juegos de calidad.

Además, los desarrolladores no tenemos que aprender a programar en un tecnología nueva, puesto que es C# y de IDE podemos utilizar Visual Studio.

Portabilidad: Lo anterior significa que podemos hacer juegos tanto para PC, Xbox Live, Zune y WP7 con modificaciones muy pequeñas (al algunas ocasiones sólo basta recompilar).

Incluso, no me extrañaria que muchos de los juegos actuales puedan liberar versiones disponibles para WP7. :D

Calidad: Al final, WP7 va a tener juegos de gran calidad, corriendo en equipos que pueden adaptarse a las necesidades de cada usuario.

Les dejo un video del primer juego que hice para esta plataforma:

F# + XNA


Cuando leí que al correr sobre .NET F# podía utilizar cualquier libreria dije "ya lo veremos", y vaya hasta el momento me ha funcionado bastante bien y para muestra me puse investigar acerca de cómo demonios meterle XNA... y es MUY SENCILLO :D


#light

#I @"C:\Program Files\XNA\v2.0\References\Windows\x86"

#r "Microsoft.Xna.Framework.dll"
#r "Microsoft.Xna.Framework.Game.dll"

open Microsoft.Xna.Framework
open Microsoft.Xna.Framework.Graphics
open System

type XNAGame = class
inherit Game as base

val mutable graphics : GraphicsDeviceManager

new() as this =
{
graphics = null
}
then
this.graphics <- new GraphicsDeviceManager(this)

override this.Draw(gameTime) =
let gd = this.graphics.GraphicsDevice
gd.Clear(Color.CornflowerBlue)
end

let Main() =
let game = new XNAGame()
game.Run()

[<STAThread>]
do Main()




:D ;) :) xD

Lo único de deben hacer es establecer el directorio donde tienen alojado el XNA, en este caso la versión 2.0 pero también lo probé con la 1.0 (oh si, mi version de F# es 1.9.3.14) porque tal parece que los assembly no estan en el GlobalAssemblyCache, otra opción es configurar el envoriment path (bucar en google) para poder acceder hasta él desde la linea de comandos.

Para compilarlo utilizé el siguiente batch:


@if "%_echo%"=="" echo off
setlocal

..\..\..\bin\fsc.exe xna.fs
if ERRORLEVEL 1 goto Exit

:Exit
pause
xna.exe
endlocal

exit /b %ERRORLEVEL%



Osea un compila y ejecuta.

Ya veré más delante que más le meto...

XNA HLSL Shaders


El día de ayer (bueno la madrugada de hoy) hicé un pequeño screencast acerca de shaders en XNA, les dejo el video y el link para descargar el código.





Tambièn les dejo la imagen de la escena lograda con este tutorial. :D




Bloom Cubemap



HLSL Shaders: Ejemplo en XNA


Hay una parte muy cool de cuando programar gráficos se trata, esa parte es el utilizar el GPU (Graphics Processing Unit) ósea la mismí­sima tarjeta de video para hacer cálculos y almacenamiento de memoria.

La Content Pipeline

Actualmente existen lenguajes de alto nivel (Cg de nVidia, HLSL de Microsoft y GLSL para OpenGL) que básicamente funcionan de la siguiente manera:


Content Pipeline


Primero obviamente lo que necesitamos es crear un shader, este lo podemos hacer desde Visual Studio, o utilizando un programa de autorí­a de shaders como el Render Monkey de ATI o FX Composser de nVidia, este archivo lo vamos a cargar en nuestra aplicación y la API gráfica se encargará de que la tarjeta de video lo compile en tiempo real, esto se hace para crear una optimización para cada tipo de hardware.
Una vez hecho esto nosotros generamos un conjunto de vértices (estos pueden ser por ejemplo un modelo 3D) activamos el shader desde nuestra aplicación y cuando el GPU realice los cálculos para la proyección tomará en cuenta los parámetros y métodos del shader; después nuestra los drivers convertirán esa salida generada (aún 3D) a coordenadas de pantalla, este proceso se le conoce como rasterización, con nuestros objetos proyectados en la pantalla podemos modificarlos una vez más, esta vez pí­xel a pí­xel. :D
Ejemplo

Supongamos que tenemos el siguiente código en un archivo .fx, podemos crear estos archivos dando click derecho en nuestro explorador de soluciones y en agregar nuevo Effect:





Código en Effect1.fx:



//Estas variables representan las matrices de posición de nuestro objeto
//la matriz de nuestra camara, y nuestra proyección
float4x4 World;
float4x4 View;
float4x4 Projection;


//Esta estructura indica que es lo que va a tomar el shader
//En este caso solo tomara la posición del vértice, podemos agregar
//las coordenadas de textura, normales, colores, etc.
struct VertexShaderInput
{
float4 Position : POSITION0;
};

//Esto es muy parecido a la estructura de entrada, pero aquí­ especificamos
//que queremos que devuelva nuestro método
struct VertexShaderOutput
{
float4 Position : POSITION0;
};

//Esta función es nuestro vertex shader
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;

//Sólo aplicaremos una sencilla transormación
float4 worldPosition = mul(input.Position, World);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);

return output;
}

//Esta función es nuestro pixel shader
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
//Aquí­ especificamos que queremos que para todo ­xel
//que se dibuje lo pinte de color rojo :)
//podemos por ejemplo regresar el valor de una textura respecto
//a la coordenada actual
return float4( 1, 0, 0, 1);
}

//Aqui especificamos nuestras técnicas
//un archivo fx puede tener varias técnicas
technique Technique1
{
//Para cada pasada especificamos que funciones vamos a llamar
//y ademas debemos de decirle bajo que perfil se compilarán
pass Pass1
{
VertexShader = compile vs_1_1 VertexShaderFunction();
PixelShader = compile ps_1_1 PixelShaderFunction();
}
}



Para utilizarlo vamos a modificar nuestra clase Game1.cs:

Primero, vamos a declarar dos objetos en nuestra clase, uno para el modelo que utilizaremos y otro para nuestro efecto:





Model _model;
Effect _effect;

Después vamos a modificar nuestra función LoadContent() para poder cargar nuestros archivos:



        protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);

_model = Content.Load<Model>("model");
_effect = Content.Load<Effect>("Effect1");

///Esto va a quitarle el efecto actual al modelo y establecera el que
///le estamos asignando
foreach (ModelMesh mesh in _model.Meshes)
foreach (ModelMeshPart part in mesh.MeshParts)
part.Effect = _effect;

// TODO: use this.Content to load your game content here
}
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

float aspectRatio = graphics.GraphicsDevice.Viewport.Width /
graphics.GraphicsDevice.Viewport.Height;


//Definimos la tecnica
_effect.CurrentTechnique = _effect.Techniques["Technique1"];

_effect.Parameters["World"].SetValue
(Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up));
_effect.Parameters["View"].SetValue
(Matrix.CreateLookAt(new Vector3(0.0f, 5.0f, -10.0f), Vector3.Zero, Vector3.Up));
_effect.Parameters["Projection"].SetValue
(Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f),
aspectRatio, 1.0f, 10000.0f));

//Actualizamos el shader
_effect.CommitChanges();

foreach (ModelMesh mesh in _model.Meshes)
foreach (Effect effect in mesh.Effects)
mesh.Draw();


base.Draw(gameTime);
}


Por último vamos a dibujar nuestro modelo con el shader correspondiente y el resultado debe de ser el modelo dibujado completamente en rojo, y esta es la imagen de nuestro primer shader:





¿No es interesante? Bueno, es nuestro "hola, mundo!" de los shaders, así­ que de aquí­ podremos partir a cosas más interesantes como iluminación, a continuación les voy a presentar una imagen de un render un poco más complejo:



Este render contiene 3 shaders, uno para los reflejos del agua, otro para el brillo de la nave, y otro que le da un efecto de zoom radial. :)


Conclusiones

Los shaders se utilizan para prácticamente todo el procesamiento de gráficos, algunas aplicaciones lo manejan automáticamente pero si quieres tener el control completo y agregar efectos a tus aplicaciones gráficas la mejor manera es meterle mano.

Los shaders no solo se utilizan en videojuegos o aplicaciones 3D, también se utilizan en edición de imágenes o ví­deo, en un futuro tutorial hablaré de como crear shaders de post producción (como los que se utilizan para las pelí­culas).

SceneGraphs en XNA


Hoy en día cuando queremos hacer un videojuego relativamente grande con gráficos 3D es muy complicado manejar los objetos necesitamos actualizar de uno por uno, para resolver este problema existe una estructura de datos muy utilizada llamada SceneGraphs, que básicamente son estructuras que almacenan toda la información de manera jerárquica dentro de un grafo o árbol y nos permite “olvidarnos” de cada objeto, ya que esta estructura se encargará de clasificarlos y manejarlos automáticamente.


Bloom Cubemap


Para este ejemplo vamos a utilizar una implementación muy sencilla que solo requerirá que almacenemos nuestros datos dentro de una colección linear de elementos esto es que cada nodo contendrá solamente un nodo hijo, con esto vamos a poder viajar a través del SG por medio de iteraciones lineares.

Durante estos recorridos nosotros vamos a poder actualizar el estado de nuestro SG, y además vamos a poder dibujar el contenido que necesite ser mostrado.


Bloom Cubemap



En nuestro ejemplo cada nodo representara un elemento gráfico del juego, este elemento puede ser un modelo, un terreno, un shader, un sistema de partículas, en fin, prácticamente cualquier objeto que podamos dibujar en la pantalla, claro en este ejemplo nos limitaremos a un modelo 3D.

Para esto lo primero que debemos de definir es nuestra Clase Objeto, que es la clase base de donde partirán todas las entidades, en este caso vamos a dejarlas con los elementos más comunes, a su vez vamos a crear una clase Modelo la cual será heredará a la clase objeto y tendrá implementada una interfaz IRendereable, que nos permitirá saber que nuestro modelo se puede dibujar.


Bloom Cubemap




Por ahora el elemento model es el único que vamos a utilizar en nuestro SG, así que vayamos a la parte interesante de este tutorial, el scene graph:


Bloom Cubemap



Como podemos observar en el diagrama anterior nuestro SG contine un nodo principal que será nuestra raíz, y un método que nos permite agregar más elementos al mismo, después tenemos nuestra clase que contiene la información a nuestra clase object, de la cual se derivan todas las clases que podemos ingresar al SceneGraph para se dibujas, además tenemos una clase que es el nodo básico de cada escena, esta clase nos permite accesar a los nodos de nuestro SG para poder hacer las llamas a los objetos correspondientes a cada nodo.


:D, El código esta disponible en mi skydrive por si alguien quiere hecharle un ojo ;)

About Me

Mi foto
carlos
Guadalajara, Jalisco, Mexico
Ver mi perfil completo

Twitter

Carlos Rivera's Facebook profile