Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Managed DirectX

Kartones
November 24, 2011

Managed DirectX

@ MAD.NUG (Madrid .NET User Group) 2006

Kartones

November 24, 2011
Tweet

More Decks by Kartones

Other Decks in Programming

Transcript

  1. Managed DirectX: Introducción a la programación con Managed DirectX orientada

    a juegos Diego Muñoz Software Developer - MCAD.NET ilitia Technologies weblog: http://kartones.net/blogs/kartones
  2. 2 Agenda 19 Enero 2006 Introducción ¿Por qué emplearlo? Aspectos

    básicos Inicialización de Direct3D Primitivas, Buffers y Meshes Depth Buffer Texturizado Iluminación Movimiento de objetos DirectInput Hands On Code ¿Hay algo más? Anexo: Demo Engine HADDD Recursos Adicionales
  3. 3 Introducción MS-DOS: Programación 2D a bajo nivel Windows 95-98:

    GDI, programación 2D mediante API Mediados de los 90: Primeros juegos 3D reales. Al poco, surgen las aceleradoras 3D: Filtrado de texturas, altas resoluciones, efectos… Aparecen las APIs 3D: OpenGL y DirectX Con la llegada de .NET: Primeros wrappers de DirectX Managed DirectX 9: API .NET para emplear DirectX sin desarrollar wrappers
  4. 4 Introducción ¿Se nota la diferencia? Parece que si ;-)

    Quake sin aceleración 3D (320x240x256 colores) Quake con aceleración 3D (1280x1024x16M colores)
  5. 5 ¿Por qué emplearlo? Permite hacer lo mismo que la

    versión nativa Rendimiento: Alrededor del 80-85% respecto a DirectX nativo con C/C++ Sencillez, rapidez, mejor estructuración de código, aprovechar las virtudes de .NET… Soporte (Beta de momento) de .NET 2.0 Distintos lenguajes (Managed C++, C#, VB.NET…)
  6. 6 ¿Por qué emplearlo? Quake 2 .NET Migración a Managed

    C++ de Quake II Tin Soldiers: Julius Caesar Juego comercial realizado 100% en C# y Managed DirectX Porque se pueden realizar videojuegos de calidad!
  7. 7 Aspectos básicos Aplicaciones: Programación orientada a eventos (aplicaciones pasivas)

    La aplicación (a grandes rasgos) espera acciones del usuario. Se emplean eventos (click, load,…) Videojuegos: Game-Loop, Render-Loop (aplicaciones activas) Game-Loop: Un gran bucle que itera hasta que termina el juego. Dentro del mismo se gestionan movimiento, IA, gráficos,… Render-Loop: Se re-dibujan todos los gráficos presentados en pantalla varias veces por segundo (FPS).
  8. 8 Aspectos básicos Render Loops: Opción 1: Sobreescribir OnPaint de

    un formulario Método simple. Convierte un formulario en un pilar de la aplicación al llevar lógica. Opción 2: Independiente, con llamadas en cada iteración del Game-Loop Método clásico. Ayuda a una buena estructuración. Opción 3: Independiente, llamado cuando la aplicación esta Idle (empleando P/Invoke) Método óptimo. Parece complejo (muy similar a la opción 2, pero en lugar de bucle activo itera sólo cuando la aplicación “está disponible”).
  9. 9 Aspectos básicos Pixel: Punto en la pantalla Vertex: Vértice

    de un polígono Texel: Pixel de una textura (puede ser varios pixeles “fisicos” al mapearse sobre un objeto)
  10. 10 Aspectos básicos Material: Propiedades de un polígono (color, refracción

    de la luz,…) Malla: Conjunto de triángulos, materiales y texturas que emplea. Polígono,Textura, etc.
  11. 11 Aspectos básicos La base de las 3D son vectores,

    Matrices y el álgebra en general. En DirectX realizaremos operaciones sobre los objetos multiplicandolos mediante matrices y vectores. Por defecto, sistema de coords mano izq. Coordenadas mano izquierda Coordenadas mano derecha
  12. 12 Aspectos básicos Normales de un triángulo. Vectores perpendiculares a

    cada vértice. Son básicas, por ejemplo para los cálculos de iluminación.
  13. 14 Aspectos básicos Matrices transformadas Matrices transformadas de DirectX: Device.Transform.World

    Espacio 3D : se emplea para situar los objetos Device.Transform.View Cámara : Información de la cámara Device.Transform.Projection View fustrum: zona de visión (explicado más adelante)
  14. 15 Aspectos básicos Librerías de DirectX Microsoft.DirectX Clases básicas, estructuras

    matemáticas Microsoft.DirectX.Direct3D Toda la parte de 3D y Helpers Microsoft.DirectX.Direct3DX Extensiones de las 3D Microsoft.DirectX.DirectInput Controladores (Teclado, Mouse, Joystick…) Microsoft.DirectX.DirectSound Sonido 2D y 3D, efectos de sonido Microsoft.DirectX.AudioVideoPlayback Videos, sonidos (gestión simplificada)
  15. 16 Inicialización de Direct3D Device La base de DirectX, todo

    gira en torno a él Encargado de dibujar en pantalla (o parte de ésta) Inicialización, finalización y pintado de escena … // Creación del Device Device dxDevice = new Device(adapter, DeviceType.Hardware, this, createFlags, presentParams); … // En la parte de representar la escena // Vaciar Pantalla/Dispositivo dxDevice.Clear(ClearFlags.Target, System.Drawing.Color.Black, 1.0f, 0); // Comienzo del dibujado de objetos dxDevice.BeginScene(); … // Fin del dibujado los objetos dxDevice.EndScene(); … // Volcado del buffer a la pantalla dxDevice.Present();
  16. 17 Inicialización de Direct3D CreateFlags Obtiene las capacidades de la

    aceleradora 3D, y si no tiene soporte Hardware, podemos escoger modo emulado por software. // Obtenemos el adaptador/tarjeta gráfica por defecto int adapter = Manager.Adapters.Default.Adapter; // Obtenemos sus capacidades 3D Caps deviceCaps = Manager.GetDeviceCaps(adapter, DeviceType.Hardware); // Si soporta H&L por hardware, lo activamos, sino emulación software CreateFlags createFlags = deviceCaps.DeviceCaps.SupportsHardwareTransformAndLight ? CreateFlags.HardwareVertexProcessing : CreateFlags.SoftwareVertexProcessing; // Comprobamos si soporta iluminación, shaders, etc. if (deviceCaps.DeviceCaps.SupportsPureDevice && createFlags == CreateFlags.HardwareVertexProcessing) createFlags |= CreateFlags.PureDevice;
  17. 18 Inicialización de Direct3D PresentParameters Determina el funcionamiento del Device

    (ventana o fullscreen, funcionamiento de los buffers, etc.) Todo esto se usa al inicializar el Device PresentParameters presentParams = new PresentParameters(); // Descartar contenido del backbuffer y volcar al front buffer directamente presentParams.SwapEffect = SwapEffect.Discard; // Modo ventana presentParams.Windowed = true; … Device dxDevice = new Device(adapter, DeviceType.Hardware, this, createFlags, presentParams); Formulario o control donde pintar
  18. 19 Inicialización de Direct3D Evitar borrados indeseados de la pantalla

    Este estilo de pintado evita borrados del formulario por repintados nativos de windows Lógicamente, el fondo será opaco (2º parámetro) // En el constructor del formulario que contendrá el Device // justo tras la llamada al InitializeComponent this.SetStyle(ControlStyles.AllPaintingInWmPaint|ControlStyles.Opaque,true);
  19. 20 Inicialización de Direct3D Back Face Culling Si una cara

    de un triángulo no está visible, no se dibuja. Para calcularlo (y evitar pérdida de triángulos) se unen los vértices de los triángulos en un determinado orden (ClockWise, CounterClockWise, None). // Modo por defecto y el adecuado para eje de coords mano izquierda dxDevice.RenderState.CullMode = Cull.CounterClockWise;
  20. 21 Inicialización de Direct3D Cámara dxDevice.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4,

    this.Width / this.Height, 1.0f, 100.0f); dxDevice.Transform.View = Matrix.LookAtLH(new Vector3(0, 0, 5.0f), new Vector3(), new Vector3(0, 1, 0)); Plano de clipping frontal Plano de clipping trasero View frustrum Cámara FOV
  21. 22 Inicialización de Direct3D Matrix.PerspectiveFovLH(_1_,_2_,_3_,_4_); 1 : FOV (ángulo/campo de

    visión) 2 : Ratio de aspecto 3 : Front clipping plane (plano de clipping frontal) 4 : Back clipping plane (plano de clipping trasero) Matrix.LookAtLH(_1_,_2_,_3_); 1 : Posición de la cámara 2 : Objetivo de la cámara 3 : Vector Arriba de la cámara dxDevice.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1.0f, 100.0f); dxDevice.Transform.View = Matrix.LookAtLH(new Vector3(0, 0, 5.0f), new Vector3(), new Vector3(0, 1, 0));
  22. 23 Primitivas, Buffers y Meshes Primitivas Las primitivas son los

    elementos básicos Puntos, lineas y triángulos Todos se forman mendiante vértices Básicos: Vector3, Vector4,… CustomVertex Position/Transformed, Colored, Textured, Normal Se pueden combinar CustomVertex myVert = new CustomVertex.PositionColoredTextured();
  23. 24 Primitivas, Buffers y Meshes Primitivas Las primitivas se pueden

    emplear de distintas formas PointList LineList LineStrip TriangleList TriangleStrip TriangleFan
  24. 25 Primitivas, Buffers y Meshes Buffers Los Buffer almacenan los

    vértices IndexBuffer: Buffer de índices de vértices Ahorra vértices al reutilizarlos empleando índices VertexBuffer: Buffer de vértices Multitud de opciones para ahorrar memoria y mejorar el rendimiento Requieren bloqueo para modificarse y desbloqueo posterior CustomVertex.PositionColored[] verts = new CustomVertex.PositionColored[3]; verts[0].Position = new Vector3(0.0f, 1.0f, 1.0f); verts[0].Color = System.Drawing.Color.Yellow.ToArgb(); … vertBuffer = new VertexBuffer(typeof(CustomVertex.PositionColored), 3, dxDevice, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Default); vertBuffer.SetData(verts, 0, LockFlags.None); … dxDevice.SetStreamSource(0, vertbuffer, 0); dxDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
  25. 26 Primitivas, Buffers y Meshes Meshes Mesh: Malla, conjunto de

    triángulos formando una figura Pueden estar divididos en segmentos DirectX los almacena en formato .X Incluye información de los materiales y texturas Direct3D proporciona algunos básicos: Box (caja/cubo) Torus (donut) Teapot (tetera) Sphere (esfera) Cylinder (cilindro) Polygon (polígono)
  26. 27 Primitivas, Buffers y Meshes Meshes Ejemplo de Cubo Se

    pueden cargar desde archivo Mesh.FromFile Más información en el SDK y código en la Demo Importante calcular sus normales si no las tiene Mesh cube = new Mesh.Box(dxDevice,width,height,size); if ((mesh.VertexFormat & VertexFormats.Normal) != VertexFormats.Normal) { Mesh tempMesh = mesh.Clone(mesh.Options.Value, mesh.VertexFormat | VertexFormats.Normal, device); tempMesh.ComputeNormals(); mesh.Dispose(); mesh = tempMesh; }
  27. 28 Depth Buffer El Buffer de profundidad controla el eje

    Z Sin activarlo, todos los objetos se pintan en el eje Z = 0, y se producen artefactos/fallos de pintado No olvidar limpiar el Z-Buffer/Depth Buffer Para mejor rendimiento, procurar pintar siempre los elementos del mas alejado (mayor Z) al más cercano (menor Z) presentParams.EnableAutoDepthStencil = true; presentParams.AutoDepthStencilFormat = DepthFormat.D16; dxDevice.Clear(ClearFlags.Target | ClearFlags.Zbuffer, Color.Black, 1.0f, 0);
  28. 29 Texturizado Un modelo sin texturas queda pobre Texturizar es

    el proceso de pintar texturas (BMPs, JPGs,…) sobre los triángulos Se puede pintar una o múltiples veces
  29. 30 Texturizado Mapeado UV Las texturas se mapean según las

    coordenadas UV Valores mayores que 1 generan mosaicos repitiendo la textura y menores que 1 “cortan” la textura U V
  30. 31 Texturizado Mapeado UV Se emplean vértices con campos de

    texturizado, y se les establecen las coordenadas UV a cada uno CustomVertex.PositionTextured[] verts = new CustomVertex.PositionTextured[6]; verts[0] = new CustomVertex.PositionTextured(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f); verts[1] = new CustomVertex.PositionTextured(-1.0f, -1.0f, 1.0f, 0.0f, 1.0f); verts[2] = new CustomVertex.PositionTextured(1.0f, 1.0f, 1.0f, 1.0f, 0.0f); verts[3] = new CustomVertex.PositionTextured(-1.0f, -1.0f, 1.0f, 0.0f, 1.0f); verts[4] = new CustomVertex.PositionTextured(1.0f, -1.0f, 1.0f, 1.0f, 1.0f); verts[5] = new CustomVertex.PositionTextured(1.0f, 1.0f, 1.0f, 1.0f, 0.0f); 0 2 5 1 3 4
  31. 32 Texturizado El objeto Texture almacena la textura Antes de

    pintar el modelo o fragmento de él, se indica la textura que empleará (o null si no pintamos textura) Texture texture1 = new Texture(dxDevice, new Bitmap(this.GetType(), “rock.bmp"), 0, Pool.Managed); dxDevice.SetTexture(0, texture1); dxDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 6);
  32. 33 Iluminación Sin iluminación, no hay sombras en los objetos

    (por defecto viene desactivada) Activando la iluminación, todo queda oscuro y hemos de definir la iluminación DirectX proporciona distintos modelos de iluminación Mediante los materiales definiremos cómo se comportan los objetos respecto a la luz, al color, etc. dxDevice.RenderState.Lighting = false;
  33. 34 Iluminación Tipos Device.RenderState.Ambient Luz ambiental, Ilumina uniformemente todos los

    objetos Sólo se le indica un color Se puede emplear siempre ya que afecta al Device y no emplea un punto de luz // Iluminación gris dxDevice.RenderState.Ambient = System.Drawing.Color.FromArgb(0x404040);
  34. 35 Iluminación Tipos LightType.Directional Luz direccional, ilumina uniformemente desde una

    dirección dxDevice.Lights[0].Type = LightType.Directional; // Color que emite dxDevice.Lights[0].Diffuse = System.Drawing.Color.Red; dxDevice.Lights[0].Direction = new Vector3(0.0f,0.0f,1.0f); dxDevice.Lights[0].Update(); dxDevice.Lights[0].Enabled = true;
  35. 36 Iluminación Tipos LightType.Spot Cono de luz (foco), con un

    alcance máximo dxDevice.Lights[0].Type = LightType.Spot; dxDevice.Lights[0].Diffuse = Color.Red; dxDevice.Lights[0].Range = 100.0f; dxDevice.Lights[0].Direction = new Vector3( 0.0f, 0.0f, 1.0f ); dxDevice.Lights[0].Position = new Vector3( 0.0f, 0.0f, 0.0f ); dxDevice.Lights[0].Falloff = 1.0f; dxDevice.Lights[0].InnerConeAngle = Geometry.DegreeToRadian( 10.0f ); dxDevice.Lights[0].OuterConeAngle = Geometry.DegreeToRadian( 15.0f ); dxDevice.Lights[0].Attenuation0 = 1.0f; dxDevice.Lights[0].Update(); dxDevice.Lights[0].Enabled = true;
  36. 37 Iluminación Tipos LightType.Point Bombilla de luz, emite en todas

    las direcciones desde un punto inicial, con un alcance máximo dxDevice.Lights[0].Type = LightType.Point; dxDevice.Lights[0].Diffuse = Color.Red; dxDevice.Lights[0].Range = 100.0f; dxDevice.Lights[0].Position = new Vector3( 0.0f, 0.0f, 0.0f ); dxDevice.Lights[0].Attenuation0 = 1.0f; dxDevice.Lights[0].Update(); dxDevice.Lights[0].Enabled = true;
  37. 38 Iluminación Materiales La clase Material indica propiedades de un

    mesh o fragmento del mismo respecto de la luz Cómo refleja la luz (Ambiental, Diffuse, Specular) Si emite luz propia de algún color (Emissive) Material material1 = new Material(); Material1.Ambient = Color.White; Material1.Diffuse = Color.White; … dxDevice.Material = material1; dxDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 6);
  38. 39 Iluminación Consideraciones Comprobar si se la tarjeta gráfica soporta

    iluminación avanzada: Device.DeviceCaps.VertexProcessingCaps.SupportsDirectionalLights Obtener el número máximo de luces soportadas por la tarjeta gráfica: Device.DeviceCaps.MaxActiveLights No abusar de la iluminación Cada fuente de luz supone realizar muchos cálculos adicionales por fotograma
  39. 40 Movimiento de objetos Todos los objetos se pueden mover

    mediante operaciones con matrices y vectores Meshes Cámara (posición y/o orientación) Posiciones de las luces Movemos desde el eje (coords [0,0,0]) Multiplicando combinamos movimientos // Situamos el mundo en [0,0,2] dxDevice.Transform.World = Matrix.Translation(0.0f, 0.0f, 2.0f); … // Dibujamos un objeto // Situamos el mundo en [1,1,1] y rotamos sobre el eje Z dxDevice.Transform.World = Matrix.Translation(1.0f, 1.0f, 1.0f) * Matrix.RotationZ(0.2f); … // Dibujamos otro objeto
  40. 41 DirectInput Permite control completo de los dispositivos de entrada

    (ratón, teclado, joysticks,…) Similar (pero más completo) a la gestión de .NET Funcionamiento simple: Configuración Inicialización y adquisición del dispositivo Lectura de entradas (en el Game-Loop) Liberado del dispositivo
  41. 42 DirectInput Inicializar y adquirir Leer entradas Liberar Device keyboardDevice

    = new Device(SystemGuid.Keyboard); KeyboardState keyboardState; // Configurar el dispositivo keyboardDevice.SetCooperativeLevel(this, CooperativeLevelFlags.Foreground | CooperativeLevelFlags.NonExclusive); // Obtener el dispositivo keyboardDevice.Acquire(); Formulario o control donde pintar keyboardState = keyboardDevice.GetCurrentKeyboardState(); keyboardDevice.Unacquire(); keyboardDevice.Dispose(); keyboardDevice = null;
  42. 43 DirectInput Dispositivo Mouse: SystemGuid.Mouse Estado de pulsación de los

    botones Valores delta de las coordenadas Diferencia entre la posición anterior y la posición actual Los joysticks, track-pads, etc. se obtienen preguntando al sistema por los dispositivos de juego conectados. Una vez inicializados, funcionan de igual forma que un Mouse Para más información sobre la obtención de Joysticks, consultar el SDK
  43. 45 ¿Hay algo más? DirectSound : Sonido 3D y música

    HLSL : Programación a bajo nivel con Shaders Animación de meshes, efectos, fog Sprites / gráficos 2D Networking, IA, Interfaz de usuario, diseño de videojuegos, … Para otra charla ;-)
  44. © 2005 Madrid .NET User Group. All rights reserved; reproduction

    in part or in whole without written permission of the author and the user group is prohibited The w ork contained in this presentation is show n AS IS w ithout any implied w arranty or liability for any damage derived from it use. All the expressions and opinions are personal and resposability of the speaker.