martes, 30 de noviembre de 2010

Recapitulación

He estado llenándome los ojos de vídeos de otros proyectos muchísimo más ambiciosos que el mio, y junto con lecturas que he hecho sobre fractales, concretamente sobre generación de terreno fractal, mi mente esta como loca ideando asteriores fractales..., mundos fractales..., universos fractales... Y veo que si sigo así, me perderé por los cerros de Úbeda.

Llegado a este punto tengo dos opciones, o sigo adelante probando cosas nuevas, o recapitulo y amarro bien lo que tengo conseguido hasta ahora.

Hasta ahora los temas que debería terminar y pulir son:

  • Inicialización del API (DirectX 9).
  • Inicialización del Engine 
  • La cámara, mejorar muchísimo su uso.
  • Añadir interacción con periféricos: Teclado, Ratón, Pad
  • Generalizar la lectura de objetos desde X3D, cerrando ya este tema.
  • Generar un formato propio que me permita englobar en un mismo archivo todo lo necesario para representar un objeto.
  • Generalizar las luces en el engine a través del API.
  • Generalizar la parte de render, embeber dentro de los objetos las instrucciones para renderizarlos.
Y más cosas que seguro que me dejo atrás.

Sólo una vez que tenga todas estas partes básicas podré ir más allá, y también empezar a darle forma al juego definitivo.

También tengo que seguir con la acotación del juego, puesto que mi meta es terminar algo, aunque sea una demo de algo más grande.

Actualizacion: Es buena idea hacer un programa visualizados/conversor/agrupador, para ver los modelos hechos en Blender, añadirle texturas y demás, ver como queda y almacenarlo en un formato propio.

domingo, 28 de noviembre de 2010

Progresos con Telemakhos III: Texturas

Hecho!

Aunque aún me faltan muchísimos conocimientos sobre texturas, me siento muy satisfecho de conseguir hacer funcionar las DirectX 9 con alguna textura.

Después de muchos cambios en las rutinas de lectura de ficheros .X3D por fin conseguí echar a andarlas en DirectX. El principal problema que me encontré fue que yo utilizaba hasta el ahora vértices indexados, de esta forma una misma esquina de un triángulo podía estar compartida entre varios triángulos.

Ahora bien, para implementar texturas, cada vértice del objeto deberá contener dos coordenadas (u, v) que indicarán que parte de la textura será proyectada. Esto provoca que para mapear objetos algo complejos, los vértices del mismo no podrán compartir coordenadas (u, v), puesto que los más probable es que las texturas para objetos complejos esten compuestas de varias subtexturas separadas entre si dentro del archivo gráfico.

Ejemplo de textura fragmentada.
El mayor problema de esto es el mayor gasto de memoria al tener que almacenar un mayor número de vértices.

Para este ejemplo utilicé el mismo objeto .X3D de esta ahora, y como textura usé una imagen cuadrada con una de las caras del famoso cubo de Hellraiser.



En mi ordenador la animación es muy fluida y la calidad muy buena, aunque al generar el video se pierda mucha calidad. En fin, aqui dejo el video:



Bueno, hasta ahora he avanzado mucho, incluso más que nunca, puesto que con opengl nunca llegué a mostrar textura alguna. Y verlo funcionando es realmente emocionante.

domingo, 14 de noviembre de 2010

Progresos con Telemakhos II: Iluminación

Voy a crear este post aparte para tratar el tema de la iluminación con DirectX 9, esto es debido a la gran cantidad de factores a tener en cuenta para iluminar una escena. Listo a continuación los punto que tendré que solventar para llevar a buen puerto la iluminación en Telemakhos.

  • Normales en la definición de los vértices.
  • Materiales describiendo las propiedades de los objetos en la escena.
  • Tipos de luces y sus propiedades.
  • Limitaciones de la iluminación a nivel de vértices.
Normales: 
La normal de un triángulo define un vector que "sale" de la cara de ese triángulo que podrá ser vista. Puesto que la iluminación es a nivel de vértices, cada vértices de los 3 que componen un triángulo, contendrá una normal. El cálculo de la normal no es demasiado complejo y puede y debe hacerse en una etapa previa al renderizado. Bueno, el cálculo no sería necesario si el fichero desde el que importo el objeto ya contuviera las normales calculadas, pero en el caso del formato .X3D exportado por Blender, estas normales no están presentes, y no me queda más remedio que calcularlas yo mismo "a pelo".

Vector Normal

Otro punto importante es que debido a que uso índices para referirme a los vértices compartidos por los polígonos, deberé calcular la normal combinada para vértices adyacentes, y esto que matemáticamente, no tiene mayor dificultad, puede generar resultados no deseados. Por ejemplo, cuando calcule la normal promediada de los vértices de un cubo, la resultante hará que la luz incida en el objeto de tal forma que suavizará las esquinas, dando la sensación de que el cubo esta algo redondeado, cosa que en casos como este del cubo, pueden suponer un problema. Por todo esto, tendré que tener 2 tipos de objetos en lo que a normales se refiere, uno donde use índices y las normales de vértices adyacentes se combinen, y otro donde no use índices y no se repitan vértices, de esta forma no habrá problemas con las esquinas redondeadas del cubo que comentaba anteriormente.


Materiales:
Los materiales definen como la luz afecta a los objetos. También define de forma indirecta qué color tiene cada objeto. Puesto que por ahora a nivel de materiales no quiero complicarme mucho la existencia, mi idea es definir un material "general" que se aplicará a todos los objetos de la escena, y el color general será una variante de blanco, esto será así porque pretendo aplicar texturas a los objetos de la escena y el color no me preocupa, tan solo debe asegurarme de que tenga igualadas las componentes RGB.

Tipos de luces:
Hay 3 tipos de luces: puntos de luz (point lights)  p.e. una bombilla, luz focal (spot lights) p.e. una linterna y luces direccionales (directional lights) como podría ser el Sol. Cada uno lleva valores asociados que definen cada fuente de luz. Todos los tipos son interesantes e iré probándolos según los vaya necesitando.

Limitaciones:
Cada tarjeta sólo permite un número determinado de luces a la vez en la escena, este dato puede ser consultado desde DirectX y debe tenerse en cuenta.
El motor de iluminación de DirectX no genera sombras generadas por objetos interpuestos a las fuentes de luz. Cuando la naturaleza de esta luz es estática, es decir, a lo largo del tiempo no va a variar su posición, podríamos hacer un precalculo de como se verían afectados los objetos y modificar "a mano" las intensidades de los colores de esos objetos para que ya de por si aparentes estar sombreados. Aun falta mucho para esto... además que en Telemakhos no creo que necesite este tipo de sombreados.

Actualización: Hecho!





Aunque el resultado es bastante crute visualmente, me siento satisfecho. Las normales son prmediadas, el material utilizado es al más simple posible y la luz utilizada es direccional. El punto más complicado de la iluminación lo encontré en el cálculo de las normales.

Normales:

Blender exporta todas las caras como cuadrados (4 vértices), y para visualizarlas en DirectX tengo que separar cada una de estas caras en 2 mas simples de 3 vértices (triángulos). Esto, como comprové, conlleva al error en el cálculo de normales, puesto que se deben calcular para cada vértice teniendo en cuenta que pertenece a una cuádrupla de vértices y no a un triángulo. Asi que, a pesar de terminar las caras siendo todas triángulos tuve que calcular las normales para cada vértice perteneciente a un cuadrado, y asi promediarlas.

Actualización: Blender no solo exporta las caras como cuadrados, tambien las exporta como triángulos, incluso un mismo objeto puede tener ambos tipos de caras. Mis rutinas de lectura de ficheros .X3D ya contemplan esto.

Tambien me he dado cuenta que para realizar una escena compleja como las de los juegos actuales no basta con definir n luces dinámicas. También deberé definir luces estáticas, y esto se consigue modificando la componente difusa de color para determinadas caras de los objetos y así "simular" que estan siendo iluminadas por, por ejemplo, una farola cercana. Y pensando en Telemakhos, deberé definir una luz direccional para la luz de alguna estrella próxima, y luego, tal vez, alguna de otro tipo para misiles, explosiones o cosas por el estilo.

El siguiente paso serán las texturas.

Nota: aunque esta forma de trabajar es algo precipitada, puesto que estoy atajando resultados, una vez consiga bastante resultados me pondré a definir mejor el engine. Por ahora simplemente estoy viendo cómo hacer las cosas y probándolas.

martes, 9 de noviembre de 2010

Progresos con Telemakhos I: Z-Buffer

En el post anterior comenté los puntos a resolver con más prioridad, eran estos:

  • Activar el Z-Buffer.
  • Dar soporte a iluminación.
  • Aplicar texturas a los objetos.
 Voy a empezar a colgar vídeos de los progresos.

Z-Buffer: Terminado
Lo cierto es que activar el Z-Buffer es bastante sencillo, el único punto delicado es saber elegir el tipo de z-buffer a usar, puesto que no todos los tipos disponibles son soportados por todas las tarjetas. En mi caso particular usé un tipo de 24 bits que es compatible con mi tarjeta gráfica. En un futuro deberé mejorar esta parte del sistema y detectar los tipos de z-buffer soportados por la tarjeta y elegir el mas adecuado en cada caso, ya sea de forma automática o dando al usuario la opción de seleccionarlo.





    sábado, 6 de noviembre de 2010

    Pasar de Blender (X3D) a DirectX

    Debido a la poca, o extensa, confusa y en inglés documentación del formato .X3D me estoy viendo obligado a usar ingeniería inversa para entender bien como funciona este formato. Hasta ahora he descubierto lo siguiente:
    1. Los ficheros .X3D exportados por Blender usan la notación de la mano derecha, mientras que por defecto, DirectX usa la notación de la mano izquierda. Esto quiere decir que el eje Z esta invertido para su uso con DirectX. Para corregir esto, tengo que hacer 2 cosas:
      • Cambiar el signo a todas las componentes Z del objeto leído desde el fichero .X3D.
      • Invertir el orden natural en que son definidos los polígonos en el fichero .X3D.
      •   Los polígonos de los objetos son definidos dentro de los ficheros .X3D como vértices y grupos de índices. Los vértices son cadenas formadas por grupos de 3 coordenadas separadas por comas. Y los índices vienen definidos por grupos de 4 índices separados por la siguiente cadena: "-1,". Teniendo en cuenta lo expuesto en el punto 1. Tendré que tener en cuenta que para Blender los polígonos están formados por 4 vértices, mientras que para DirectX deberán ser triángulos exclusivamente, "rompiendo" cada polígono de 4 vértices en 2 polígonos de 3 vértices.

      Por ejemplo: si leemos esta lista de índices: "0 1 2 3 -1, 4 5 6 7 -1, ", deberemos transformarla así:
      • Cambiar el orden en que son definidos los vértices y pasar de un grupo 4 vértice a 2 grupos de 3 vértices: "0 2 1, 0 3 2".

      En cuanto a los vértices leídos, bastará con invertir el signo de la componente Z para todos los vértices.

      Actualización: Una vez aplicados estos conceptos a la lectura de ficheros .X3D, el programa ya es capaz de leer la geometría de objetos desde ficheros externos, creados en Blender y exportados como ficheros .X3D con formato XML. Incluso con geometrías mas complejas como la de la nave que diseñé hace unos meses, el programa lo lee sin problemas. El único fallo o contratiempo que encuentro son las proporciones de la nave, que parece algo "engordada", posiblemente por los parámetros con los que estoy configurando la cámara. Otro contratiempo es la falta de un Z-Buffer que esconda poligonos que no deberían verse.

      Los posibles puntos siguientes serían:
      • Activar un Z-Buffer para esconder polígonos no deseados.
      • Empezar a trabajar con iluminación para dotar de más realismo a los objetos.
      • Dar soporte para texturas.