francisco jesus ruiz pons ©. Con la tecnología de Blogger.

6/1/13

Feliz año, estas navidades el blog ha estado algo inactivo, por compromisos familiares, avanzar con los proyectos de clase y demás. Pero aquí viene una entrada nueva.

Esta entrada es un poco mas técnica, para programadores. Voy a subir y comentar la practica que nos han mandado hacer en navidad para la asignatura de bajo nivel.

Programación de bajo nivel es programar en un lenguaje mas cercano a la maquina, no solo el lenguaje, también las instrucciones que se utilizan, lo que implica conocer la maquina sobre la que se va a programar.

Parte de lo que se nos pide para esta practica es:


-Que esté libre de corrupciones de memoria
- Que no abuse del espacio de pila
- Que no use recursos de lenguaje C poco portables

- Ausencia de llamadas innecesarias a librerías matemáticas en runtime
- Ausencia de reservas y liberaciones de memoria en runtime
- Uso de inst. rápidas en lugar de otras más lentas o potencialmente lentas
- Uso correcto del código inline
- Uso de enteros o coma fija en lugar de coma flotante
- Uso eficiente de la memoria

De entre la lista de efectos que nos daban a elegir, yo he elegido este:
Esfera de puntos rotando sobre varios ejes.

El lenguaje para la practica es C y la plataforma es PC.

He hecho 2 versiones, una es en coma flotante(esfera roja) y la otra en coma fija(esfera azul) en formato 24:8(24 bits para la parte entera y 8 para la parte fraccionaria).



Si hubiese rotado con matrices, tendría que hacer multiplicación de matrices, y eso son muchas operaciones.
En lugar de eso, he realizado las rotaciones utilizando cuaterniones.

La mayor parte del trabajo se realiza en los inner loops(la parte interna de los bucles que se van a repetir muchas veces en cada fotograma) ya que no es lo mismo optimizar instrucciones que se van a ejecutar 1 vez por fotograma que optimizar otras que se ejecutan mil o dos mil veces cada fotograma.

No voy a comentar las operaciones en coma fija o como operar con cuaterniones porque ya hay muchos sitios que hablan de lo mismo, pero si voy a hablar de una cosa, los saltos condicionales.

Los procesadores actuales, tienen un sistema de predicción por el cual si los saltos condicionales salen siempre igual, le cuesta muy poco, pero si sale un resultado diferente en cada fotograma, le cuesta muchísimo.

Pero, si hay que escribir en una pantalla, y la esfera puede tener puntos fuera de la pantalla, ¿como se puede hacer sin un condicional?

La idea que se me ocurrió es la siguiente:
w1 es la longitud de la pantalla menos uno(width -1), h1 es la altura de la pantalla menos uno(height -1).

#define Max(A,B) ((B & ((A-B) >> 31)) | (A & (~((A-B) >> 31))))
#define Min(A,B) ((B & (~((A-B) >> 31))) | (A & ((A-B) >> 31)))

   color = 0x0000ccff; // se carga el color azulado
#ifdef noifs
   xp=Max(xp,0);//si la x proyectada es menor que cero, la pongo a cero
   xp=Min(w1,xp);//si es mayor que la longitud, se situa a la longitud maxima
   yp=Max(yp,0);//si la y proyectada es menor que cero, la pongo a cero
   yp=Min(h1,yp);//si es mayor que la altura, se limita a la altura maxima

//con esto se consigue que en lugar de pintar fuera de los limites, pinte en los bordes, pero
//como no es muy bonito ver puntos raros en los bordes
// voy a hacer que si pinta en un borde pinte negro        

//ahora se calcula una mascara que sera todo ceros si esta pintando en borde
// y como cualquier numero multiplicado por cero, es cero, si esta en algun borde, pintara negro
   color  = color & ( (((-xp)>>31) & ((xp-w1)>>31) & (((-yp)>>31) & ((yp-h1)>>31) ); 
        
 #else 
   //Si la x o la y proyectadas quedan dentro de la pantalla se pinta
   if (( xp >= 0) && (xp < w) && (yp >= 0) && (yp < h))
 #endif
     pixels [ xp + (yp * pitch)] = color;


El código compila en plataformas Unix y Windows.

                                                            Fuentes    Ejecutable




3 comentarios:

  1. Interesante entrada, veo que os dan caña con eso de la optimización, ciertamente un tema importante, sino luego se hace un juego como FarCry 3 y necesitas el MareNostrum para moverlo.

    ResponderEliminar
  2. Hola. Estoy bastante interesado en aprender algo sobre la base del renderizado. En esta práctica que has tenido, renderizas directamente haciendo tú los cálculos de donde va a ir cada pixel.

    ¿Sabes alguna documentación donde pueda aprender de ésto (libro, web, etc)? leo tu código y más o menos lo puedo comprender, pero cuando empiezas a mezclar la tercera dimensión, me hago un lío.

    Por cierto, bastante interesante tu blog ;)

    ResponderEliminar
    Respuestas
    1. Te pongo links a algunos articulos interesantes de la wikipedia que te daran una idea de por donde ir, depende de si quieres rasterizar una escena o hacer raytracing.

      http://en.wikipedia.org/wiki/Raster_graphics

      http://en.wikipedia.org/wiki/Rasterisation

      http://en.wikipedia.org/wiki/Ray_tracing_(graphics)

      Mucha suerte.

      Eliminar