Buenas, tras estar unos días fuera, vuelvo con la saga de tutoriales para programar 3D en NDS, en esta ocasión aprenderemos todo lo que la NDS nos permite sobre texturas, y veremos un nuevo modo de proyección, el Modo Ortogonal, con el que crearemos figuras 2D con todas las opciones del modo 3D.
Bien, sin más preámbulos, empezamos!
1- Texturas, qué son y cómo se usan
Bien, hasta ahora hemos aprendido muchas cosas en 3D (luces, normales, transformaciones), pero todavía nos quedan la mitad de conceptos para terminar, ahora vamos a ver qué son las texturas.
Pues una textura es cuando, por ejemplo, queremos pintar una figura con una imagen pegada a él, como por ejemplo esta:
Podemos ver un cubo a la que le hemos "pegado" una imagen, para que el objeto dé mayor realismo, bueno pues eso es lo que llamamos una textura.
Pero si decicimos usar texturas tenemos que decirle a OpenGL cómo la usaremos (en qué parte de la VRAM la metemos, si se repite, las coordenadas de textura que tienen, si se mezcla o no con un color). Todo a su tiempo, lo primero que vamos a ver es un pseudocódigo de cómo usaremos las texturas aquí:
int main(){ Iniciar VRAM para almacenar texturas Activar sistema de texturas Cargar nuestra textura en VRAM con OpenGL while(1){ Empezar3D(); DibujarObjeto Texturizado Actualiza3D(); } Eliminar textura de VRAM para ahorrar espacio }
1.1 - La VRAM de la NDS
Bien, en el primer paso de cómo cargar una textura dice que tenemos que iniciar la VRAM para cargar nuestras texturas, bueno, ¿cómo hacemos eso?, bien lo primero que hay que saber sobre la VRAM de la NDS es que tiene 650kb (más o menos) de memoria para ambas pantallas, y por si fuera poco, la VRAM está dividida en bancos, cada banco se encarga de cargar una cosa (fondos, sprites, texturas, bitmaps) etc. Voy a poneros una pequeña tabla de VRAM para que sepáis por encima cómo esta estructurada:
VRAM_A --> 128KB, usado por Fondos, Sprites y Texturas de la pantalla principal VRAM_B --> 128kb, tiene los mismos usos que el banco A, pantalla principal VRAM_C --> 128KB, Fondos, sprites y texturas, pantalla inferior VRAM_D --> 128KB. Fondos, sprites y texturas, pantalla inferior VRAM_E --> 64KB, Paletas, Fondos y Sprites, pantalla principal VRAM_F --> 16KB, Paletas, Fondos y Sprites, pantalla principal VRAM_G --> 16KB, Fondos, Sprites y Paletas, pantalla principal VRAM_H --> 32KB, Fondos y Paletas, pantalla inferior VRAM_I --> 16KB, Paletas, Fondos y Sprites, pantalla inferior
Como hemos visto en la tabla de la VRAM, sólo podemos acceder a los bancos A y B de VRAM para cargar texturas (podemos usar también los bancos C y D pero nos quedatíamos sin memoria para la otra pantalla), así que mejor usad los bancos A B para texturas, son 256KB, así tendréis de sobra.
Ahora que sabemos los bancos de VRAM que usaremos para las texturas, tenemos que decirle a la NDS que los vamos a usar, todo esto con este código:
// Iniciamos Banco A (128KB) para texturas vramSetBankA(VRAM_A_TEXTURE); // También el banco B (128KB) vramSetBankB(VRAM_B_TEXTURE);
Bien, con esto tendremos inicializada la VRAM y podremos cargar las texturas, no se os olvide ningún paso, si no la textura no se verá.
1.2 - Iniciando el sistema de texturas
Ahora que hemos iniciado la VRAM para las texturas tenemos que decirle a OpenGL que las vamos a usar, todo ello con la función glEnable() para activar funciones:
// Activa el sistema de texturas glEnable(GL_TEXTURE_2D); // Desactiva el sistema de texturas glDisable(GL_TEXTURE_2D);
Con sólo esto tendremos iniciado el sistema de texturas, podemos continuar.
1.3- Cargando la textura en OpenGL
El siguiente paso consiste en cargar la textura en los bancos de VRAM que hemos solicitado (A y B), esto de cargar la textura va así:
1- Cargar archivo de textura en RAM 2- Generar espacio en VRAM para la textura (la NDS puede con 256 texturas) 3- Seleccionar la textura para meterle datos 4- Meter datos de la textura
Bien, lo primero que debemos hacer, según este pseudocódigo, es cargar en RAM el archivo de la textura, como en el principio del tutorial suponí que sabíais C a nivel medio, no hace falta que explique esto...
Luego, tenemos que asignar memoria en VRAM para la textura que vamos a usar, todo con esta función:
void glGenTextures(int n_tex, int &slot); n_tex --> Numero de texturas a generar slot --> Slot dondese ha cargado la textura Ejemplo: int slot; // Variable para guardar el slot de la textura (0-255) // Genera la textura glGenTextures(1, &slot);
Bien, ya hemos asignado hueco para la textura, para modificarla y añadirle configuraciones, tenemos que seleccionarla, con esta otra función:
void glBindTexture(GLenum id, int slot); Selecciona la textura numero 'slot' id ----> Ponedlo a 0 para que funcione slot ---> Slot donde está la textura Ejemplo: glBindTexture(0, 3); // Selecciona la textura del slot 3
Una vez generada y seleccionada la textura, vamos a meter los datos de la misma, todo con esta otra función:
glTexImage2D(0, 0, Glenum modo, Glenum ancho, GLenum alto, 0, GLenum generacion, void* pixeles); Configura una textura previamente asignada y seleccionada. Los 2 primeros valores y el sexto ponedlos a 0 para que funcione. modo --> Modo de mostrar la imagen: GL_RGB para RGB, GL_RGBA para 16 bits ancho y alto --> Dimensiones de la textura en la macro de OpenGL generacion --> Modo de generar la textura, de momento poned TEXGEN_TEXCOORD pixeles --> Datos de pixeles de la textura Ejemplo: glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_32, TEXTURE_SIZE_32, 0, TEXGEN_TEXCOORD, datos); Carga en VRAM una textura RGB de 32x32 pixeles, se genera por coordenadas de textura
Una vez hecho todo esto, la textura estará cargada completamente en VRAM, dejo el código completo:
// GENERAMOS LA TEXTURA int slot; glGenTextures(1, &slot); // SELECCIONAMOS LA TEXTUA glBindTexture(0, slot); // CONFIGURAMOS LA TEXTURA glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_32, TEXTURE_SIZE_32, 0, TEXGEN_TEXCOORD, tex.datos);
1.4 - Eliminando una textura de VRAM
Esto es solo un detalle, cuando no vayamos a usar más una textura y queramos borrarla de la VRAM para ahorrar espacio, usamos esta función:
void glDeleteTextures(int ntex, int *slot); Borra una textura de VRAM ntex --> Numero de texturas a borrar, normalmente 1 slot --> El slot donde está guardada (debe estar en una variable) Ejemplo: glDeleteTextures(1, &slot); // Borra una textura de VRAM
Con esto borraremos una textura de VRAM para poder volver a usarla.
1.5 - Dibujando un objeto texturizado
Bien, ahora que tenemos la textura cargada en VRAM, vamos a pegarla a un cuadrado, lo primero que hay que hacer para que la textura se vea es seleccionarla con glBindTexture, y después dibujaremos el objeto que queramos, como siempre hemos hecho:
// Selecciona la textura glBindTexture(0, slot); // Dibuja objeto texturizado glBegin(GL_QUADS); glTexCoord2f(1, 0); glVertex3f(-0.8, -0.8, 0); glTexCoord2f(1, 1); glVertex3f(-0.8, 0.8, 0); glTexCoord2f(0, 1); glVertex3f( 0.8, 0.8, 0); glTexCoord2f(0, 0); glVertex3f( 0.8, -0.8, 0);
Bien, ahora que vemos el código anterior hay una cosa que nos hemos saltado por alto, es decir, las coordenadas de textura, estas son las que se encargan de pegar la textura en el objeto correspondiente, veamos un ejemplo de objeto con coordenadas de textura:
Podemos ver un objeto al que se le han aplicado coordenadas de texturas, y que la textura se a pegado al mismo. OpenGL administra las coordenadas de textura con 2 valores, S, para la anchura, y T, para la altura (también llamadas UV). Un consejo, los valores ST de las coordenadas de textura van de 0 a 1, en float.
Si nos volvemos a fijar en la imagen, vemos que la esquina inferior izquierda tiene una coordenada de textura de 0, 0, y que la esquina superior derecha es de 1, 1. teniendo estas coordenadas se mostrará la textura completa.
Ahora para definir una coordenada de textura (recuerdo que debe definirse antes que el vértice afectado) usamos esta función:
void glTexCoord2f(float s, float t); Define una coordenada de textura que afectará a un vértice s --> Valor horizontal t --> Valor vertical (de 0.0 a 1.0) Ejemplo: glTexCoord2f(1, 0); // Coordenada de textura en la esquina inferior derecha de un cuadrado
Sabiendo lo que son las coordenadas de textura, pongo el ejemplo del cuadrado texturizado con comentarios:
// Seleccionamos la textura a usar glBindTexture(0, slot); // Dibujamos un cuadrado con coordenadas de textura glBegin(GL_QUADS); glTexCoord2f(1, 0); glVertex3f(-0.8, -0.8, 0); // Inferior derecha glTexCoord2f(1, 1); glVertex3f(-0.8, 0.8, 0); // Superior derecha glTexCoord2f(0, 1); glVertex3f( 0.8, 0.8, 0); // Superior izquierda glTexCoord2f(0, 0); glVertex3f( 0.8, -0.8, 0); // Inferior izquierda
Bien, repasaros todo el código de las texturas, ya que es casi todo lo que vamos a dar sobre ellas (en tutoriales siguientes veremos los cube maps).
2- Modo Ortogonal, una manera 2D de ver 3D
Bien, hasta ahora hemos estado dibujando 3D, cuando también podemos dibujar figuras 2D con las mismas opciones que el 3D (luces, texturas, transformaciones), en el primer tutorial de esta saga vimos la perspectiva, que era la que rasterizaba la imagen para convertirla en 3D, bueno pues existe otro modo de proyección llamado proyección ortogonal (o modo ortho), con el cual podremos dibujar figuras como antes solo que no se tendrá en cuenta la profundidad de los objetos.
Bien, pero, ¿qué utilidad le podemos dar a esto? Pues muchas, dibujar textos, dibujar Sprites 3D, mezclar 2D con 3D etc...
Os interesáis más con el modo ortogonal? Pues ahora aprenderéis a iniciarlo, todo con este código:
// Reinicia la matriz de proyeccion glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Inicia el modo ortogonal glOrtho(-3, 3, -3, 3, 0.1, -1000); // Limites de la proyección en FLOAT, izquierda, derecha, abajo, arriba, cerca y lejos // Recomiendo ponerlo a esos valores para que toda la escena 3D se vea afectada
Bien, una vez iniciéis la matriz de proyección en este modo, podéis seguir dibujando, solo que lo que dibujéis será 2D.
Bien, pero ¿cómo podemos mezclar ambos modos, 2D y 3D, con las mismas opciones? Todas las respuestas a vuestras preguntas está en este código, en el cual interatuaremos directamente con las matrices para cambiar 3D a 2D y viceversa.
while(1){ // Empieza a dibujar 3D empieza3D(); // Dibuja las figuras 3D Dibujar3D(); // CAMBIA A MODO ORTOGONAL glMatrixMode(GL_PROJECTION); glPushMatrix(); // Guarda la proyeccion en la pila glLoadIdentity(); // Reseteala glOrtho(-3, 3, -3, 3, 0.1, 1000); // Cambia a modo ortogonal glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); // Guarda la modelacion y reseteala // Dibuja la escena 2D Dibujar2D(); // Vuelve a modo 3D glPopMatrix(1); // Restaura la modelación glMatrixMode(GL_PROJECTION); glPopMatrix(1); // Restaura la proyección en perspectiva // Actualiza la escena 3D Actualiza3D(); }
Si no sabéis cómo interactuar con matrices aún es que os habéis saltado el segundo tutorial.
Bien, para terminar, os dejo un par de ejercicios para asimilar todo lo que hemos aprendido hoy.
Ejercicio 6
Este ejercicio está abordado a el uso de las texturas, administraremos VRAM, generaremos texturas, y las cargaremos allí, para que con solo cambiar una variable cambiemos la textura actual que se dibujará en un cubo con coordenadas de textura. NOTA: Las texturas no pueden estar en un formato cualquiera, así que las transformaremos con una utilidad llamada GRIT, incluida en la descarga de esta práctica
Con Arriba-Abajo cambias la textura seleccionada
Con Stylus mueves la cámara
Descarga: http://www.mediafire.com/?0b85ibajvc2b59c
Ejercicio 7
En este otro ejercicio veremos cómo usar el modo ortogonal para crear un simple sistema de Sprites 3D, con posibilidades de rotacion, escalado, movimiento, y todas las que permie el Hardware 3D de la NDS.
Con Stylus seleccionas un Sprite3D
Con Arriba-Abajo escalas el Sprite 3D seleccionado
Con Derecha izquierda rotas en XY el Sprite 3D seleccionado
Descarga: http://www.mediafire.com/?czgarcjxi387nfe
Bien, este es el fin de este cuarto tutorial, en la próxima entrega veremos todo lo que permite la NDS sobre transparencias de objetos, y veremos también sobre niebla.
Bueno, hasta entonces, saludos!
~Actualmente estudiando Ingeniería de las Tecnologías de la Telecomunicación en la Escuela de Ingenieros~
WoW otra vez felicitaciones
WoW otra vez felicitaciones por la calidad de tus tutoriales
Genial
Los tutoriales están perfectos, pero queria preguntar si OpenGL tambien está disponible para otras consolas, como por ejemplo PSP.
Saludos!
Es algo parecido
Para PSP hay algo parecido que se llama PSPGU que tienen las funciones parecidas que en OpenGL, pero es lo mismo, si aprendes esto en PSP estará chupado (pero esto solo vale en C).
En PC se usa mucho OpenGL para gráficos en 3D, lo que hay para NDS es como una "copia" de esta librería xD
Saludos!
~Actualmente estudiando Ingeniería de las Tecnologías de la Telecomunicación en la Escuela de Ingenieros~
proyecto :P
hola que hay!! xDDD quiero tutoriales al principio de todo lo que tenga que ver con creaciones de juegos para NDS porfavor :D ..mi untencion es crear SLENDERMAN para nds no es para fama ni ser el primero ni nada de eso solo quiero aprender y divertirme :'D este es mi msn por si la dudas de mi proyectito editado [at] hotmail [dot] com gracias de antemano y un saludo!!
Editado: Dar a conocer datos privados en el foro publico no esta permitido. Se requiere que vuelva a leer las normas de la comunidad. Gracias. The Dark Master.
Oye
no pueres publicar tu correo electronico Xd
ahh!!
ahh!! lo siento ;P