lunes, 24 de junio de 2013

5 .-. Luces y Sombras.

Bien, vamos a iluminar un poco las cosas para ver nuestra caja. También voy a aprovechar este post para agregar algo de texto a la pantalla que me permita ver cual es la posición de la cámara y así poder depurar mejor nuestro mini mundo.

Vamos con lo más fácil primero, el texto. Para poder escribir texto en nuestro juego tenemos dos opciones: renderizar texto como una mesh y que los textos aparezcan dentro de juego (por ejemplo los nombres de los NPCs encima del muñeco) o bien texto en 2D para mostar datos como por ejemplo en el HUD. De momento vamos con el 2D el 3D lo veremos más adelante.


Para crear texto 2D en nuestro juego vamos a las declaraciones de la clase Motor, arriba de todo y escribimos esto:

    Private Fuente As Direct3D.Font

Y en PosConfigurarDX tenemos que iniciar el tipo de fuente que vamos a emplear (después de  Caja = Mesh.Box(DP3, 1, 1, 1))


Fuente = New Microsoft.DirectX.Direct3D.Font(DP3, New System.Drawing.Font("Arial", 12, FontStyle.Regular))

Este objeto "Fuente" va a tener un tamaño de 12 podeis regular el tamaño o el tipo de fuente así como su estilo. Recordad que este estilo de fuente simplemente va a permitir escribir en 2D, eso quiere decir que mi pantalla tiene un sistema de coordenadas 2D y no 3D como el mundo del juego. Recordad siempre que, en la pantalla, la posición 0,0 es la esquina superior izquierda.

Para poder emplear "Fuente" creo un Sub como este dentro de Motor.

    Public Sub PintaTexto(ByRef donde As Point, ByRef str As String)
        Try
            Fuente.DrawText(Nothing, String.Format(": {0}", str), donde, Color.Green)
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

Este Sub recibe un punto (2D)y un texto "str" para escribirlo. Podemos indicar el color de la fuente, yo le he puesto Green. Para comprobar que funciona vamos a Motor y en el Render ponemos esto antes de la linea de DP3.Material = MAterial.

 PintaTexto(New Drawing.Point(20, 20), "Hola Render")

Si ejecutáis vereis el mensaje "Hola Render" en la parte izquierda de la pantalla.

Por ultimo vamos a las luces. Para ellos vamos a hacer una cosa, crearemos dos luces que iluminarán la caja (recordad que la caja está en 0,0,0 en el origen de coordenadas y tiene 1 de lado, sería bueno emplear figuras si teneis poca visión 3D como yo) desde dos puntos distintos. Una luz será roja y le dará desde la izquierda (es decir desde X-) y otra verde que le pegará desde X+. Como nuestra cámara está situada en 0,0,-2 lo que deberíamos de ver al empezar es un cuadrado con media cara verde y media cara roja.

Creamos en Motor un Sub que va a contener las luces:

    Public Sub Luces(ByRef DP3 As Direct3D.Device)
        Try
            DP3.Lights(0).Position = New Vector3(-2, 0, 0)
            DP3.Lights(0).Type = LightType.Point
            DP3.Lights(0).Range = 2
            DP3.Lights(0).Attenuation0 = 0.2

            DP3.Lights(0).AmbientColor = Direct3D.ColorValue.FromArgb(Color.Red.ToArgb)
            DP3.Lights(0).DiffuseColor = Direct3D.ColorValue.FromArgb(Color.Red.ToArgb)
            DP3.Lights(0).Enabled = True
            DP3.Lights(0).Update()

            DP3.Lights(1).Position = New Vector3(2, 0, 0)
            DP3.Lights(1).Type = LightType.Point
            DP3.Lights(1).Range = 2
            DP3.Lights(1).Attenuation0 = 0.2

            DP3.Lights(1).AmbientColor = Direct3D.ColorValue.FromArgb(Color.Green.ToArgb)
            DP3.Lights(1).DiffuseColor = Direct3D.ColorValue.FromArgb(Color.Green.ToArgb)
            DP3.Lights(1).Enabled = True
            DP3.Lights(1).Update()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

Vamos a explicar un poco aunque es bastante intuitivo. 
- Position es el lugar 3D donde está la luz situada.
- Type es el tipo de luz: puede ser direccional, punto o focal.
- Range es el alcance de la luz su potencia.
- Attenuation0 es lo que pierde la luz de fuerza con la distancia, en nuestro caso la luz pierde 0.2 de Range por cada unidad 3D recorrida.
- Ambient, Diffuse, Specular son los distintos valores que puede tener la luz en sus colores y que afectarán a los valores correspondientes de los materiales que creemos.
- Enabled pues enciende la luz o la apaga.
- Update actualiza los valores.

Por último tenemos que agregar este control de luces a la secuencia de cosas que se renderizan, para ello vamos a retocar el Render de Motor. Lo dejamos así:

    Public Sub Render(ByRef DP3 As Direct3D.Device, ByRef vc As Vector3)
        Try

            DP3.Clear(ClearFlags.Target, Color.Black, 1.0F, 0)
            Luces(DP3)
            DP3.BeginScene()
            DP3.VertexFormat = CustomVertex.PositionColored.Format
            PintaTexto(New Drawing.Point(20, 20), "Hola Render")
            DP3.Material = MAterial
            DP3.Transform.World = Matrix.Translation(0, 0, 0)
            Caja.DrawSubset(0)
            PintaTexto(New Drawing.Point(20, 80), "CAM:" & vc.X & "," & vc.Y & "," & vc.Z)
            DP3.EndScene()
            DP3.Present()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

Hemos hecho algunos cambios, para empezar hemos puesto un parámetro VC de tipo vector3 que nos permitirá acceder mejor a los datos de la cámara.
Antes del BeginScene indicamos las luces para que se ejecuten. También hemos añadido un par de impresiones de texto, una con el mensaje "HOLA RENDER" y otra que nos va a decir la posición de la cámara.

Ahora sí, podeis ejecutar la aplicación y comprobar el movimiento de las teclas así como la variación de los valores de la cámara. El efecto es un poco extraño porque la cámara está mirando todo el rato hacia 0,0,0. Pero es un inicio.

No hay comentarios:

Publicar un comentario