Logo de Torre de Babel
Portada Libros Diseño web Artículos Glosario RSS
Buscar

Torre de Babel >> Diseño web

Desde hoy Torre de Babel cuenta con una nueva sección, llamada Diseño web y que puede encontrarse en el panel de secciones, entre Libros y Artículos. Como es fácil imaginar el tema central de dicha sección es el diseño web, abordado desde sus pasos más básicos describiendo HTML, CSS y, a medida que se avance, otros aspectos como DOM, jQuery, HTML 5, etc.

En realidad esta sección es un blog independiente, creado y mantenido por mi hijo David al que le encanta este tema desde hace mucho tiempo. Los contenidos, tanto los ejemplos como la redacción, son suyos, aunque en un futuro no descarto hacer alguna aportación personal, en lugar de agregar entradas de esa misma temática en mi sitio de toda la vida.


Publicado el 26/7/2010

Shaders en la práctica (II) - Un vertex shader con transformaciones variables

Partiendo del código del VS de la entrada anterior de esta serie, es fácil introducir algunos cambios a fin de que la transformación que se aplica a los vértices no sea constante sino variable con el tiempo. Para ello se puede utilizar el parámetro uniforme time (un parámetro al que tiene el acceso el shader y que no puede modificar, procede de la aplicación).

El código del shader, una vez modificado, sería el siguiente:

uniform float time; // Tiempo que lleva ejecutándose el shader

void main()
{
    vec4 v = gl_Vertex; // Tomamos el vertice de origen

    // Se aplica una transformación variable y periódica
    v.x = v.x * abs(sin(time)) + 0.1;
    v.y = v.y * abs(cos(time)) + 0.1;

    // Se aplica establece el vértice transformado como posición
    gl_Position    = gl_ModelViewProjectionMatrix * v;
    ...

La declaración uniform float time al inicio permite al shader acceder al citado parámetro time, en el que la aplicación facilita los segundos que lleva en ejecución. Este dato es suficiente para aplicar una transformación variable y de tipo periódico, gracias a las funciones sin() y cos(). Ambas son de tipo periódico, pero los valores negativos no interesan para este caso, por lo que se obtiene el valor absoluto.

Al aplicar sin() sobre un eje y cos() sobre otro, lo que se consigue es que mientras la geometría crece en un uno de ellos decrezca en el otro y viceversa. El efecto, del que pueden verse dos capturas puntuales en la figura inferior, es que el cubo (o cualquier otra geometría que se cargue en el programa), se estira y encoge alternativamente en los ejes X e Y.

Captura de dos instantes de la ejecución del VS

En lugar de aplicar un factor meramente multiplicativo a los ejes, que provoca un cambio de tamaño en la geometría, podrían realizar transformaciones de rotación variables en el tiempo, de forma que la escena vaya girando al completo en cualquiera de los ejes o en varios de ellos simultáneamente.


Publicado el 25/7/2010

Píldora histórica (9)

El primer microprocesador fue fabricado por Intel en el año 1971, se denominó Intel 4004 y fue fabricado con tecnología de 10.000 nanómetros, lo cual permitió introducir en su pequeño tamaño nada menos que 2.300 transistores. Como su nombre deja vislumbrar, se trataba de un procesador de 4 bits y se utilizó principalmente en las calculadoras de la época ya que 4 bits son todo lo necesario para representar un dígito decimal en aritmética BCD.

Intel promocionó el 4004 como el microprocesador que ofrecía la misma potencia que el ENIAC pero con el tamaño de una uña y un consumo ridículo. Su conjunto de instrucciones era muy reducido y sencillo y la única memoria interna con que contaba eran los registros: 16 de 4 bits, tenía arquitectura Harvard (como los microcontroladores), en contraposición a la arquitectura Von Neumann que usan los microprocesadores actuales.

En comparación, el microprocesador más potente lanzado por Intel hasta la fecha se ha fabricado con tecnología de 32 nanómetros e integra 2.300 millones de transistores, es como si estuviese formado por un millón de procesadores 4004. Este monstruo está formado por 8 núcleos capaces de ejecutar 16 hilos en paralelo, tiene un ancho de palabra de 64 bits y una memoria interna (cache) de 24 MB.


Publicado el 18/7/2010

Múltiplos de 5, los dedos de una mano y Excel 2010

Portada del libro Guía práctica de Excel 2010 Las personas solemos dar un significado especial a ciertos números y, casualidad o cuestión de cuántos dedos tenemos en las manos, esos números suelen ser múltiplos de 5. La décima edición de un certamen siempre se destaca como especial, sobre la novena o la undécima. Casi nadie celebra el vigésimo cuarto o vigésimo sexto aniversario de su unión, pero sí el vigésimo quinto (las conocidas bodas de plata). Las conmemoraciones de la mayoría de eventos históricos siguen esa misma regla.

Quizá por esa misma razón este libro, a pesar de haber sido escrito con la misma ilusión y empeño que escribí el anterior y con que será escrito el siguiente, tiene algo que, para el que estas líneas suscribe, lo hace especial. Éste es el centésimo libro que publico, mi libro número cien, y aparece publicado a pocas semanas de que se cumplan veinticinco años de la primera vez que publiqué. Son dos hitos importantes a los que, como curiosidad, también se unen las coincidencias de que ésta es la quinta revisión del libro sobre Excel 2000 que publiqué hace ahora diez años. Cinco, diez, veinticinco y cien, cuatro números que resumen un cuarto de siglo, miles de horas de trabajo y mucha historia personal.

Mi primera publicación apareció en la desaparecida revista MSX-Club (ver portada debajo, clic sobre ella para ampliar), un sencillo programa para ordenadores MSX cuya característica más destacable no era convertir el teclado del ordenador en un sintetizador, sino el hecho de que al ejecutarse el programa redefinía todo el conjunto de caracteres ofreciendo a continuación una pantalla de instrucciones con aspecto manuscrito.

Portada de la revista MSX-Club de octubre de 1985

Tras publicar algún programa más en esta revista escribí mi primer libro, al que han seguido otros 99 más hasta llegar al que ocupa esta entrada. En realidad he escrito varios libros más, ya que no todos he llegado a publicarlos. Por el camino quedaron, completamente terminados, un libro sobre el lenguaje Logo, otro que trataba el editor para programadores BRIEF, un tercero sobre el lenguaje RM-COBOL 85 y alguno más inacabado.

Me apunta mi buen amigo Andrés, tras haber leído esta entrada, lo siguiente: Que no se te olvide que el año 2010 es múltiplo de 5 y el año 1985 también. Que el libro es Excel 2010, que es múltiplo de 5, o que tu primera publicación fue en Octubre (mes 10) del año 1985. ¡¡¡Ah!!! Que la carrera que acabas de sacarte tiene una duración de 5 años. Gracias por la aportación.


Publicado el 16/7/2010

Píldora histórica (8)

Desde que en 1946 se fabricase el primer transistor en los Bell Laboratories este dispositivo semiconductor ha revolucionado el mundo, haciendo posible, entre otras cosas, la existencia de los actuales microprocesadores y lo que ha venido a denominarse informática personal. Los transistores están presentes en ordenadores, teléfonos móviles, televisores, lavadoras y una largo etcétera.

Lo que es menos conocido es que el diseño del primer transistor no procede de los citados Laboratorios Bell. De hecho, cuando se fue a registrar la patente del nuevo dispositivo ésta fue rechazada ya que existía una patente previa, solicitada en 1926 y concedida en 1930, a nombre de Julius Edgar Lilienfeld en la que se describía el funcionamiento del que hoy es conocido como transistor de efecto campo.

Esquema de la patente de Lilienfeld

Se desconoce si Lilienfeld llegó a intentar construir el dispositivo que había diseñado, ya que se encontró en una situación similar a la de Charles Babbage y su máquina analítica: la tecnología del momento no estaba lo suficientemente avanzada como para hacer posible la fabricación con materiales semiconductores, pero si duda su patente, dos décadas antes de la fabricación en los Laboratorios Bell, le hace merecedor del título de padre del transistor. Además llegó a patentar muchos otros inventos que aparecen en su biografía cuya lectura recomiendo.


Publicado el 14/7/2010

Shaders en la práctica (I) - Un vertex shader simple

Un vertex shader es un programa que recibe como entrada una serie de argumentos y genera unos resultados, casi como cualquier programa de ordenador. Su objetivo general es transformar vértices, si bien puede también influir en otros parámetros como el color o las coordenadas de textura.

En esta entrada y las siguientes utilizaré el lenguaje OGLSL para escribir los shaders, al ser éste el lenguaje asociado a OpenGL, que es la API gráfica más utilizada, y ser también multiplataforma, algo que no se aplica por ejemplo a DirectX y HLSL.
Para codificar y probar los distintos ejemplos usaré la herramienta Shader Maker (ver entrada del 17 de mayo), simplemente porque está más actualizada que ShaderDesigner y permite trabajar con GS, una posibilidad que no ofrece este último programa.

Parámetros de entrada

Desde un VS se tiene acceso a los siguientes parámetros de entrada:

  • gl_Vertex: Es un vector en coordenadas uniformes (4 elementos) que representa al vértice que debe procesar el shader.
  • gl_Normal: Vector con las coordenadas 3D de la normal asociada al vértice.
  • gl_Color: Se trata de un vector con los cuatro componentes (R,G,B,A) del color del vértice.
  • gl_MultiTexCoordN: Contiene las coordenadas de textura de la unidad de textura N. En el hardware actual existen múltiples unidades de textura. Es habitual que N oscile entre 0 y 7.

Además de la información relativa al vértice que debe procesarse, el VS también tiene acceso a una serie de datos invariantes, procedentes de OpenGL y que no puede modificar, conocidos como uniforms. Los más relevantes son:

  • gl_ProjectionMatrix: Matriz de proyección. Es la matriz 4x4 habitual.
  • gl_ModelViewMatrix: Matriz de modelo-vista.
  • gl_ModelViewProjectionMatrix: Matriz con el producto de las dos anteriores. Permite proyectar los puntos sin necesidad de realizar el producto de proyección y vista por cada vértice existente.
  • gl_NormalMatrix: Matriz 4x4 obtenida a través de la trasposición y cálculo de inversa de la matriz modelo-vista. Se utiliza para la transformación de la normal.
Parámetros de salida

El único resultado que obligatoriamente debe generar un VS es el vértice, transformado o no, que se enviará a las siguientes etapas del cauce gráfico. El parámetro al que debe asignarse dicho vértice es gl_Position y, al igual que gl_Vertex, es un vector con cuatro elementos, es decir, la posición se establece en coordenadas homogéneas.

Además el VS también puede modificar otros datos, compartidos con los PS y GS, denominados genéricamente varyings. Gracias a ellos puede influir en el color que se asociará al vértice y las coordenadas de textura. Dichos elementos variables son los siguientes:

  • gl_FrontColor: Color que se asignará a la cara delantera de la primitiva.
  • gl_BackColor: Color que se asignará a la cara trasera de la primitiva.
  • gl_TexCoord[N]: Coordenadas para la textura N-sima.

Los tres parámetros son vectores de cuatro elementos, los dos primeros en formato (R,G,B,A) y el tercero en coordenadas homogéneas, como (X,Y,Z,W).

Los varying son campos que permiten compartir información entre los diferentes shaders de un programa, pero no tienen una incidencia directa sobre el resultado final aplicado a la geometría. La asignación de un color a gl_FrontColor por parte del VS, por ejemplo, no se traduce en la asignación de ese color al píxel final. Será decisión del PS, posiblemente a partir del parámetro recibido en gl_FrontColor, el color que finalmente se utilice.

Composición del VS

Conociendo exclusivamente los parámetros de entrada y salida que puede utilizar un VS, ya es posible escribir uno sencillo que, por ejemplo, lleve a cabo una transformación fija sobre los vértices de una geometría. El objetivo es duplicar el tamaño en el eje Z y reducirlo a la mitad en el eje X.

El ejecutar el programa Shader Maker se inicia un proyecto con unos shaders básicos. Con la opción Test Model se modifica el modelo sobre el que se probarán. En este caso he elegido un cubo, de forma que el aspecto inicial es el que puede verse en la figura inferior.

Aspecto inicial del cubo, sin aplicar el VS

Usando el ratón sobre el área de visualización es posible tanto rotar el modelo como hacer zoom. Es importante que la opción Use GLSL Program, el primer check-box que hay en el apartado Geometry Processing, esté marcado, de lo contrario no se usarían los shaders para generar la imagen.

A continuación modificaremos el código que aparece en la página Vertex Shader del editor. El código quedará así:


void main()
{
    vec4 v = gl_Vertex; // Tomamos el vertice de origen

    // Reducimos dimensión en eje X
    v.x = v.x * 0.5;
    // y duplicamos en eje Z
    v.z = v.z * 2;

    // Se aplica establece el vértice transformado como posición
    gl_Position    = gl_ModelViewProjectionMatrix * v;

    // Parámetros de comunicación del VS con el PS, se dejan
    // tal cual
    gl_FrontColor  = gl_Color;
    gl_TexCoord[0] = gl_MultiTexCoord0;
}

Como puede verse, el código se asemeja en gran medida a cualquier programa escrito en C. Existe una función main(), que contiene las sentencias a ejecutar; se declaran variables como v, de tipo vec4, y se realizan operaciones de asignación y producto. El operador * en este contexto, sin embargo, no realiza siempre un producto escalar entre dos números. En la sentencia gl_Position = ... se está llevando a cabo el producto de dos matrices: la de modelo-vista-proyección por la matriz de una fila y cuatro columnas que representa al vértice.

Una vez escrito el código del shader, hay que hacer clic en el botón Compile and Link para compilarlo y vincularlo al programa que genera la imagen. En ese momento podrá verse que el cubo se convierte en un paralelepípedo (véase la figura inferior). Marcando y desmarcando la opción Use GLSL Program se puede activar/desactivar, respectivamente, el uso del VS, viendo así la imagen original sin shaders y la que se genera con éstos.

Código del VS y efecto que genera sobre la escena

Las últimas dos sentencias del VS proceden del esqueleto que genera Shader Maker, siendo su finalidad entregar un color y coordenadas de textura al PS. Éste los utiliza para realizar su trabajo, por lo que de eliminarse no funcionará correctamente.

El efecto que se consigue no es nada espectacular. Sin embargo, si se analiza qué está ocurriendo al activar el VS es fácil deducir algunos aspectos interesantes:

  • El programa que se ha escrito actúa sobre un único vértice, que recibe como entrada en gl_Vertex, y genera un único resultado, en gl_Position. El resto de los vértices de la geometría, por tanto, no influyen en el cálculo del vértice que está procesando el VS en un momento dado.
  • Una vez compilado y enviado a la GPU, el VS realmente se ejecuta en paralelo sobre un conjunto de vértices de la geometría. En este caso concreto la transformación de los vértices del cubo se lleva a cabo en un único ciclo, ya que existen tan solo ocho vértices y el hardware empleado permitiría ejecutar en paralelo varios cientos de vértices. Para conseguir este mismo rendimiento en una CPU habría que crear explícitamente múltiples hilos y, en el mejor de los casos, se podrían procesar hasta 4 u 8 vértices por ciclo, dependiendo del microprocesador.
  • Aunque en este ejemplo la transformación aplicada al vértice es constante, siempre se divide y multiplica por 2, nada impide que esos factores sean variables, tal y como se mostrará en el ejemplo de la próxima entrada, permaneced atentos.

Publicado el 2/7/2010

Curso de shaders

Torre de Babel - Francisco Charte Ojeda - Desde 1997 en la Web