16 de abril de 2008

El siempre molón Motion Blur

Hace tiempo que sentía curiosidad por este efecto. Su definición según Wikipedia es:
Motion blur o "trazo confuso de movimiento" es el aparente movimiento a gran velocidad de objetos en una imagen quieta (fotografía) o una secuencia de imágenes como una película o animación.

Es decir, el típico difuminado que el ojo humano percibe al ver cosas que van muy rápido. Una cosa tan "tonta" puede hacer que una visualización que funciona a una tasa de 30 imágenes por segundo con motion blur tenga un aspecto mucho más realista que la misma funcionando a 60 sin este efecto.

Cuando empecé a mirarme cómo implementarlo, vi algunos métodos un poco "arcaicos" como por ejemplo guardar en una textura los frames anteriores al actual y hacer blending para ir mezclándolos entre ellos o usar el búfer de acumulación para conseguir un efecto parecido, pero los resultados eran bastante... feos.

Hoy en día, gracias a los ahora tan habituales shaders, se pueden conseguir efectos más sofisticados y con un resultado mucho más realista, sin que necesariamente eso signifique un coste de cálculo alto.

Precisamente el ejemplo que pondré más adelante aplica la técnica explicada en la presentación titulada "Stupid OpenGL Shader Tricks", de Simon Green. Este documento es bastante antiguo (2003) y creo que hoy en día hay técnicas que dan resultados mucho mejores (si no me equivoco, usando el Geometry Shader), pero el algoritmo que se explica es muy, muy sencilo y muy fácil de implementar.

Básicamente se trata de usar las matrices Model y View del frame actual y del anterior para generar un vector de velocidad en el vertex shader. Este vector se transforma al espacio imagen y se pasa al pixel shader para efectuar el blur en la dirección que marque. Sin más rollos (y además el código es bastante claro), el ejemplo lo podéis bajar haciendo click en la siguiente imagen:



En el ejemplo no se hace así, pero he comprobado que una manera de aplicar el efecto que queda bastante bien en muchas situaciones es guardar todas las velocidades de todos los objetos de la escena en una textura y hacer todo el blur como un paso de post-proceso sobre toda la pantalla (y creo que queda mejor haciendo el blur desde el pixel que se trata hacia el exterior, y no como se hace en la demo).


No hay comentarios: