Introducción
Éste es un sencillo tutorial, que explica el uso de las DirectX en Visual Basic 5 o superior, ya que anteriormente se realizó un tutorial con las mismas intenciones para Visual Basic .NET. Con respecto al rendimiento de ambos, apenas hay diferencia. Sólo que uno genera código bytecode y el que usaremos aquí genera código nativo.
Comienzo
Una vez creado el proyecto, un EXE estándar, debemos agregar la siguiente referencia, para ello 'clikeamos' en Proyecto->Referencias, entonces se abrirá un diálogo y buscamos DirectX 8 for Visual Basic Type Library, hecho ésto ya estamos listos para empezar.
Primer paso, incialización
La inicialización y configuración del dispositivo abstracto, que accede al hardware por nosostros, requiere del uso de un objeto clave, que será declarado de la siguiente forma, para ello usamos un nombre significativo:
Dim dispositivo As Direct3DDevice8
Aparte del objeto principal, obligatoriamente debemos declarar otros 4 objetos más.
Dim dx As DirectX8 ' La madre de todo el desmadre
Dim d3d As Direct3D8 ' El hijo de la madre, se usa para inicar y asignar el dispositivo antes mencionado
Dim FuncionesDX As New D3DX8 ' Contiene mucho de los métodos para crear y usar gráficas, cómo primitivas, texturas, etc..
Dim modo As D3DDISPLAYMODE ' Se usa al comienzo para parametrizar el modo de visualización
Una vez creado los objetos declarados, podemos empezar a inicializar el dispositivo, algo que se puede resumir en unas cuantas líneas:
| Código: | Set dx = New DirectX8
Set d3d = dx.Direct3DCreate()
d3d.GetAdapterDisplayMode 0, modo
Dim parametros As D3DPRESENT_PARAMETERS
parametros.SwapEffect = D3DSWAPEFFECT_DISCARD
parametros.BackBufferFormat = modo.Format
parametros.BackBufferWidth = Me.Width
parametros.BackBufferHeight = Me.Height
parametros.Windowed = True
Set dispositivo = d3d.CreateDevice(0, _
D3DDEVTYPE_HAL, _
Me.hWnd, _
D3DCREATE_SOFTWARE_VERTEXPROCESSING, _
parametros)
dispositivo.SetVertexShader D3DFVF_XYZRHW Or D3DFVF_TEX1 Or D3DFVF_DIFFUSE Or D3DFVF_SPECULAR
'Transparencias
dispositivo.SetRenderState D3DRS_ALPHABLENDENABLE, True
dispositivo.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA
dispositivo.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA
|
Ya tenemos una aplicación DirectX, que no hace nada.
El Render y algunos objetos gráficos (Sprites y Vertices)
Aquí trataremos principalmente el dibujo poligonal, haciendo una rápida vista al funcionamiento del objeto Sprite, el cual no he conseguido hacer funcionar, y al parecer no soy el único de los muchos usarios que lo han intentado sin éxito en toda la red. Es por ello que se recurre a los surfaces o polígonos para el tratamiento bitmap.
La forma para declarar e inicializar un objeto Sprite se puede resumir todo en una sóla línea.
Dim MiSprite As D3DXSprite: Set MiSprite = FuncionesDX.CreateSprite(dispositivo)
Ahora disponemos de un objeto Sprite, pero el Sprite por si sólo no hace nada, necesitamos la textura o imagen que queramos mostrar. Por lo tanto habrá que declarar e inicializar la textura que vestirá nuestro Sprite. Hay que añadir que es posible usar todo tipo de formatos bitmaps, pero para evitar embrollos innecesarios yo recomendaría usar para Sprites que usan Canal Alpha o transparencia, un fichero PNG, que previamente desde un editor gráfico hayamos asignado el color transparente.
Dim textura As Direct3DTexture8
Set textura = FuncionesDX.CreateTextureFromFileEx(dispositivo, _
App.Path & Fichero, _
D3DX_DEFAULT, _
D3DX_DEFAULT, _
1, 0, _
D3DFMT_UNKNOWN, _
D3DPOOL_MANAGED, _
D3DX_FILTER_NONE, _
D3DX_FILTER_NONE, _
&HFF00FF, _ ' El color Key o transparencia (si se trata de un PNG dará igual)
ByVal 0, ByVal 0)
Es posible que a muchos no les funcione el objeto Sprite, desconozco el por qué, pero cómo realmente mi intención sólo era mostrar cómo se hace, pues así fue. Ahora nos meteremos de lleno con los vértices. Un vértice es el objeto más básico de un objeto 3D, que a su vez está construido por triángulos y éstos hechos con líneas o segmentos, y éstas hechas con vértices. Para crear nuestros objetos podemos usar un tipo llamado D3DTLVERTEX, pero mejor usaremos un tipo de nuestra propia cosecha el cual es idéntico, pero más que nada para aprender su funcionamiento.
| Código: | Private Type VERTICE
X As Single
Y As Single
Z As Single
rhw As Single
color As Long
specular As Long
tu As Single
tv As Single
End Type
|
Entonces, vamos a lo siguiente, declaramos un array VERTICE. En éste caso haremos un rectángulo plano que en un futuro podremos usar cómo un Sprite, cómo aquel que no 'furulaba'
Dim MisVertices(0 To 5) As VERTICE ' o D3DTLVERTEX
Podemos asignar sus atributos mediante una sencilla función, clarificando un poco el código.
| Código: | Private Function CrearVertice(X As Single, Y As Single, Z As Single, rhw As Single, color As Long, specular As Long, tu As Single, tv As Single) As VERTICE ' o D3DTLVERTEX
CrearVertice.X = X
CrearVertice.Y = Y
CrearVertice.Z = Z
CrearVertice.rhw = rhw
CrearVertice.color = color
CrearVertice.specular = specular
CrearVertice.tu = tu
CrearVertice.tv = tv
End Function
|
Y ahora procedemos a introducir los datos más comodamente.
| Código: | MisVertices(0) = CrearVertice(0, 0, 0, 1, RGB(255, 255, 255), 0, 0, 0)
MisVertices(1) = CrearVertice(Me.Width, 0, 0, 1, RGB(255, 255, 255), 0, 1, 0)
MisVertices(2) = CrearVertice(0, Me.Height, 0, 1, RGB(255, 255, 255), 0, 0, 1)
MisVertices(3) = CrearVertice(Me.Width, Me.Height, 0, 1, RGB(255, 255, 255), 0, 1, 1)
|
Cada vertice puede pintarse de un color, con lo que podremos generar triangulos con un amplio espectro, cual arcoiris se tratase. En éste caso, sólo lo hemos puesto de blanco, pero para añadirle una textura sólo tendremos que llamarla con un setTexture, algo que veremos más adelante en el proceso del render. Las coordenadas gráficas de la textura están representadas por los atributos tu (horizontal o la X) y tv (vertical o la Y). También se tendrá en cuenta a la hora de dibujar un polígono el sentido de unión de sus vértices, ya que de lo contrario podríamos estar mostrándolo al revés. Normalmente el sentido de la unión de vértices se hace en sentido contrario a las agujas del reloj. Con más tiempo y en otra ocasión también trataremos de las Normales, que es el sentido hacia donde se muestra la textura.
Bueno, una vez que ya tenemos preparado el objeto gráfico con su correspondiente textura, ya sólo nos falta pasar al Render. El Render, es el proceso de pintado en el buffer, y el volcado de éste a la pantalla visible. Para ello usaremos un método muy similar al que usa OpenGl, por si alguien no lo ha usado lo explicaré. Consiste en dos métodos del objeto dispositivo, una de comienzo, BeginScene, y otra de fin, EndScene. Dentro de éstos dos métodos, se registrarán todas las peticiones gráficas y todas las peticiones gráficas que se encuentren fuera de los mencionados métodos se omitirá. Luego hay un tercer método, Present, que se encarga de llevar estas peticiones al "sumo sacerdote" o "manager" que invocará con su magia todo lo necesario para que veamos los gráficos por la pantalla.
| Código: | ...
...
' Bucle infinito
dispositivo.BeginScene() ' Comienzo del buffer
' Aqui dibujamos lo que queramos
dispositivo.EndScene() ' Fin del buffer
dispositivo.Present() ' Muestra por pantalla el resultado
...
...
|
Ahora que ya sabemos el procedimiento del Render, sólo falta sustituir la línea ' Aqui dibujamos lo que queramos, del ejemplo anterior, usando por ejemplo un Sprite (si alguien le funciona que se cuelgue una medalla).
| Código: | MiSprite.Begin
MiSprite.Draw texura, ByVal Rectangulo, vector2DScala, vector2DRota, 0, vector2DPosicion, &HFFFFFF ' &HFFFFFF=Blanco
MiSprite.End
|
O para dibujar un polígono u objeto3d... (Ésto funciona en el 90% de los casos), el resto es posible que no tenga instalado DirectX
| Código: | dispositivo.SetTexture 0, textura
dispositivo.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, MisVertices(0), Len(MisVertices(0)) ' D3DPT_TRIANGLESTRIP=crea triangulos a partir de vertices sueltos, 2 = el numero de triangulos o primitivas, MisVertices(0)=El array de los vertices, Len(MisVertices(0))=El numero de vertices a procesar |
Ahora a ponerse a practicar, porque DirectX guarda muchos secretos, espero que les sea util, chao!!
En otra ocasión explicaré cómo cargar objetos 3D, con formato X usando mallas y cosas así... |