Anuncios Google

Tutoriales de programación 3D para NDS: 6- Toon Shading y Cube maps

 

Buenas, llegamos a la recta final para programar 3D en la NDS, en esta ocasión aprenderemos a usar el Toon Shading y los Cube Maps, las cuales son las únicas cosas que nos faltan para haberlo dado todo. Luego en el siguiente tutorial daré unas funciones de control y optimización y de regalo un juego 3D (simple) para asimilar todo lo aprendido.

Bueno, sin más preámbulos, empezamos!

 

 

1- Otra forma de sombrear: Toon Shading

En el tutorial anterior vimos cómo usar la niebla para dar sombreados a nuestros terrenos en 3D, pues en esta ocasión veremos otro tipo llamado Toon Shading, el cual se basa en sombrear los vértices del modelo/objeto 3D usando para ello las luces y materiales. Todo esto puede que os suene a rollo, pero este efecto se usa en muchos juegos, como los de The Legend of Zelda para NDS, ahora veréis un ejemplo de toon shading:

Aquí podemos ver una imagen a la izquierda con "plastic shading" (otro sombreado no soportado por el hardware de NDS), y a la derecha el mismo modelo de la izquierda solo que aplicándole el efecto Toon Shading, con esto conseguimos que las partes no iluminadas e iluminadas se distingan rápidamente. Esto puede sonar muy bien para nuestros juegos 3D pero tiene una serie de inconvenientes:

- Debemos usar las luces 0 y 1 para que surta efecto, las luces 2 y 3 no podemos usarla ya que el Hardware las ignora

- No podemos usar colores para el modelo, esto se suele suplir usando materiales o texturas directamente

- Debemos dar el color de toon shading a cada uno de los 32 slots que tiene (lo veremos más adelante)

Bien, ahora que sabemos los inconvenientes, aquí expondré un pequeño pseudocódigo de cómo vamos a usar el Toon Shading, aquí va:

int main(){
 
   Iniciar3D();
 
   INICIAR LUCES 0 Y 1
 
   CONFIGURAR LOS 32 SLOTS DE TOON SHADING
 
   while(1){
        Empezar3D();
 
        DIBUJAR OBJETOS CON MATERIALES O TEXTURAS (NO USAR COLORES)
 
        Actualiza3D();
    }
    return 0;
}

Bien, lo primero que hay que hacer es iniciar las luces 0 y 1 para que se vea el efecto Toon Shading, para el que no se acuerde las luces se configuran con esta función:

void glLight(int luz, u16 color, v10 x, v10 y, v10 z);
 
            Configura una luz para ser usada
            luz ---> Numero de luz (0, 1, 2 o 3) (Toon Shading solo soporta 0 y 1)
            color --> Color de la luz de la macro RGB15()
            x, y, z --> Posicion de la luz
 
Para usar la luz tenemos que decirlo al glPolyFmt()
 
glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE | POLY_FORMAT_LIGHT0 | POLY_FORMAT_LIGHT1);
 
Con esto mostramos las luces 0 y 1
 
Estos conceptos se vieron con más detalle en el tutorial 3 sobre iluminación

Digo también que para que salga el Toon Shading tenemos que decírselo al glPolyFmt(), añadiendo el parámetro POLY_TOON_HIGHLIGHT, si no se especifica esto el efecto no se verá.

Bueno, después de configurar las luces 0 y 1 (repito: no podemos usar las luces 2 y 3 paa esto), tenemos que saber que, como la niebla, el Toon Shading tiene 32 slots para aplicarle el color del sombreado, el slot 0 es usado por los vértices completamente oscuros  y va subiendo hasta el 31 donde los vértices son completamente luminosos, todo esto y más con esta función:

void glSetToonTableRange(int slot_inicial, int slot_final, u16 color);
 
              Configura varios slots de Toon Shading
 
              slot_inicial --> Slot inicial de configuración
              slot_final --> Slot donde termina la configuración
              colo ---> Color en RGB15() de los slots
 
Ejemplo:
 
glSetToonTableRange(0, 15, RGB15(31, 31, 31));  
 
Los slots del 0 al 15 tienen el color blanco (el modelo se verá blanco en las zonas no iluminadas)

 

Fácil no? Con esto ya podemos usar el Toon Shading, ahora sólo tenemos que dibujar el objeto afectado, teniendo en cuenta que no podemos usar colores (en teoría si, pero por razones de Hardware el canal R del color no se ve), así que para ello tenemos 2 alternativas, usar materiales o texturas, los cuales se vieron con detalle en tutoriales anteriores.

 

Bien, terminamos con esto con el código completo:

// Configuramos las luces 0 y 1
glLight(0, RGB15(31, 31, 31), floattov10(-1), floattov10(1), floattov10(0));
glLight(1, RGB15(31, 31, 31), floattov10(1), floattov10(-1), floattov10(0));
 
// Configuramos los Slots de Toon Shading (0-31)
glSetToonTableRange(0, 15, RGB15(15, 15, 15));  // Los slots del 0 al 15 son grises
glSetToonTableRange(15, 31, RGB15(31, 31, 31)); // Los otros más iluminados son blancos
 
while(1){
 
   // Aplicamos el Toon Shading
   glPoylFmt(POLY_ALPHA(31) | POLY_ID(0) | POLY_CULL_NONE | POLY_TOON_HIGHLIGHT);
 
   // Definimos un material para el objeto
   glMaterialf(GL_AMBIENT, RGB15(8,8,8));
   glMaterialf(GL_DIFFUSE, RGB15(24,24,24));
   glMaterialf(GL_SPECULAR, RGB15(0,0,0));
   glMaterialf(GL_EMISSION, RGB15(0,0,0));
 
   // Dibujamos objeto con toon shading
   glCallList(modelo);
}

Solo con hacer esto ya tendremos el modelo 3D con este efecto, primero configuramos las luces, los slots del efecto, lo ponemos con el glPolyFmt(), y finalmente dibujamos el objeto...

 

2- Usando Cube Maps, otra manera de texturizar

Bien, el siguiente apartado, el miy mencionado, va a tratar sobre los entornos o cube maps.  En tutoriales anteriores vimos cómo texturizar objetos mediante las coordenadas de textura, pero si dijera que los podemos hacer de otra forma, ésta sería mediante los normales de iluminación, este efecto trata de calcular las normales de iluminación convirtiéndolas en coordenadas de textura, por ejemplo: si quisiéremos hacer que un objeto refleje lo que hay a su alrededor (como un espejo), pues usamos esto, para asimilarlo nada mejor que una imagen:

 

En la imagen anterior podemos ver una esfera 3D la cual, mediante una textura, aplicamos el efecto Cube Map, y ésa textura envuelve el objeto (todo esto pasando las normales de iluminación a la matriz de texturas).

 

Bien, ahora que hemos aprendido lo que es, vamos a aprender a usarla, al hacerlo no vamos a perder nada, así que con este código lo explico en un momento:

INICIAR EL SISTEMA DE TEXTURAS
 
CARGAR LA TEXTURA EN VRAM EN EL MODO CUBE MAP
 
while(1){
 
     CALCULAR LA MATRIZ DE TEXTURA (CONVERTIR NORMALES EN COORDENADAS DE TEXTURA)
 
    SELECCIONAR TEXTURA USADA COMO CUBE MAP
 
    DIBUJAR OBJETO CON EL CUBE MAP
 
}

 

Bien, primero y fundamental es iniciar las texturas, es decir, iniciar los bancos A y B de VRAM para texturas y activarlas con glEnable(), se vió en el otro tutorial.

Luego las cargamos en VRAM, usando el mismo método, solo que en el glTexImage2D() tenemos que decirle que la textura se va a generar mediante normales de iluminación, no como coordenadas de textura, todo esto con esta función:

glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_32, TEXTURE_SIZE_32, 0, opciones_generacion, datos_textura);
 
Todos los parámetros se explicaron en el tutorial 4
 
Lo que cambia aquí es que el en argumento "opciones generacion", en vez de poner TEXGEN_TEXCOORD tenemos que poner lo siguiente:
 
(TEXGEN_NORMAL | GL_TEXTURE_WRAP_S | GL_TEXTURE_WRAP_T).
 
Poniendo eso la textura se cargará en el modo Cube Map y podremos usarla.

 

Bien, ya hemos iniciado las texturas y hemos cargado en VRAM una en el modo Cube Map (calcular normales + repetir coordenada S + repetir coordenada T), lo siguiente que tenemos que hacer es configurar en el bucle while() la matriz de texturas, todo con este código:

// Selecciona la matriz de texturas
glMatrixMode(GL_TEXTURE);
 
// Reseteala
glLoadIdentity();
 
// Escala la matriz de textura para los cube maps
// Los datos recomiendo ponerlos a INT o en FLOAT
glScalei(-64 << 16, 64 << 16, 0 << 16);
 
// NOTA: El valor a escalar hay que moverlo 16 bits a la izquierda para que se vean los cambios entre valor y valor
 
// NOTA: Si hacemos transformaciones a los objetos, debemos ponerla también en la matriz de textura, p.e: si rotamos 60º, aquí habría que poner también glRotateX(60);
 
// Una vez configurada, reinicia el modelado
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

 

Una vez configurada la matriz de texturas tenemos que seleccionar la textura que usaremos como Cube Map (obvio), lo hacemos con glBindTexture(0, slot);

Después de esto, dibujamos el objeto normalmente, definiendo sus normales de iluminación y se calcularán en la matriz de textura con el código de antes, como no tenemos que aplicarle un material para que los normales tengan efecto.

Termino con un ejemplo final de cómo usamos los cube maps:

// Iniciamos las texturas
vramSetBankA(VRAM_A_TEXTURE);
vramSetBankB(VRA_B_TEXTURE);
 
// Cargamos la textura en VRAM
glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_128, TEXTURE_SIZE_128, (TEXGEN_NORMAL | GL_TEXTURE_WRAP_S | GL_TEXTURE_WRAP_T), datos);
 
// Dibujar objetos con el cube map...
while(1){
 
      // Configura la matriz de texturas
     glMatrixMode(GL_TEXTURE);
     glLoadIdentity();
     glScalei(-64 << 16, 64 << 16, 0 << 16);
 
     // Una vez configurada, reinicia el modelado
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
 
     // Dibuja el objeto con el cube map (las normales y el material deben estar definidos)
    glMaterialf(GL_EMISSION, RGB15(31,31,31));
    glMaterialf(GL_DIFFUSE, RGB15(31,31,31));
 
    glCallList(modelo);
}

Bien, con esto tendremos nuestro objeto con la textura en modo cube map, repasad bien todo el código, y si hay alguna duda ponedla en los comentarios. Pondré ahora un par de ejercicios para practicar lo aprendido y termino:

 

Ejercicios

 

Ejercicio 10

En este ejercicio usaremos el Toon Shading aprendido anteriormente, tendremos 2 modelos rotando con el Toon Shading y veremos cómo cambia su aspecto, le aplicaremos texturas a los objetos (recordad que no deberíamos poner colores):

 

Descarga: http://www.mediafire.com/?1uqzosrf3dl6g7d

 

Ejercicio 11

Ya vimos que con el Toon Shading podemos sombrear los objetos sin apenas esfuerzo, pero y si los texturizamos usando los Cube Maps?, el resultado sería sorprendente, solo hay que ver la imagen para notarlo, tendremos los 2 modelos otra vez, solo que esta vez, aplicando Cube Maps podemos darle apariencia a madera, cristal etc... Todo ello usando una sola textura.

Con Arriba-Abajo cambias la textura de cube map seleccionada

 

Descarga: http://www.mediafire.com/?sh851txsvrhyolf

 

 

Bueno, este ha sido el fin de este sexto tutorial, el siguiente desgraciadamente será el último, ya que hemos dado casi todo lo que nos puede ofrecer la NDS de 3D, daremos una clase rápida de optimización y un ejemplo final de un juego (simple) en 3D, usando la "librería" que hemos estado acumulando en estos tutoriales.

 

Bien, hasta entonces, saludos!

 


~Actualmente estudiando Ingeniería de las Tecnologías de la Telecomunicación en la Escuela de Ingenieros~


Anuncios Google

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

Hola IndexAlpha9 Y vas a

Hola IndexAlpha9

Y vas a poder terminar el tutorial?


Imagen de Andresmargar

Ups...

Tengo hecha la parte de las funciones, pero como acaba de empezar el instituto y todo, no me ha dado tiempo de terminar el juego final xD

 

En cuanto pueda lo publico entero, saludos!


~Actualmente estudiando Ingeniería de las Tecnologías de la Telecomunicación en la Escuela de Ingenieros~

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.