El final de las líneas de procesamiento de funciones fijas (y cómo seguir adelante)

Las tuberías de función fija no tienen más negocio en nuestras tarjetas de video. Esto es lo que necesita saber sobre ellos y cómo hacer el cambio para alejarlos de ellos, si aún no lo ha hecho..

En el principio: El auge del hardware de gráficos

Había una vez, cuando el desarrollo del juego (o la codificación de cualquier cosa que tuviera que ver con gráficos en tiempo real, en realidad) se limitaba a escribir en una matriz relativamente pequeña de intensidades de color (la buffer de cuadro) y enviándolo al hardware, podrías hacer lo que quisieras con él. Podrías dibujar a la imagen una, diez o cien veces. Podrías pasar sobre el búfer de cuadros nuevamente para hacer algunos efectos netos. En resumen, cualquier cosa que su procesador fuera capaz de hacer, podría hacerlo con la imagen que se envía al monitor. Esto le permitió hacer cosas realmente geniales y creativas, pero la gente nunca (o pocas veces) las usó en esa medida. Pero por qué?

La respuesta: porque era lenta. Una imagen de 640 × 480px (una resolución común en ese momento) contiene 307,200 píxeles. Y las CPU eran mucho más lentas entonces, que realmente no se podía hacer mucho en el corto tiempo que se le daba para dibujar ese marco. Después de todo, si desea seguir dibujando a 30 FPS, solo tiene alrededor de 30 ms para actualizar su lógica de juego y renderizar en la pantalla, y eso debe incluir la sobrecarga de la intercomunicación con el hardware. No era mucho.

Luego vinieron las GPUs cool con tuberías de representación. Usted, el desarrollador, se encargaría de actualizar la lógica del juego y de enviar sus texturas y triángulos a la GPU, y se encargaría del trabajo pesado y el procesamiento de números. Esos fueron tuberías de representación de función fija (FFPs): lo que significa que no pudo configurar el funciones desempeñaron. Puedes decirles "haz que la niebla sea gris oscura" o "¡no hagas la iluminación por mí!" y usted podría configurar muchos de los otros parámetros, pero el funciones se quedaron. 

El hardware estaba cableado y era muy especializado para que realizara algunas operaciones estándar en sus datos. Y debido a que estaba cableado de esa manera, fue mucho más rápido que hacerlo en su procesador. Pero un inconveniente fue que pagabas mucho por esa velocidad: pagabas en flexibilidad. Pero si alguna vez quiso dibujar algo complejo, la CPU simplemente no fue lo suficientemente rápida, y enviar sus vértices a la GPU fue la única opción.

Esto es más o menos cómo funcionaba la tubería de función fija. La imagen no tiene la intención de ser una representación precisa, sino de darle una pista de cómo se realizó todo..

Las exigencias de un mejor realismo

El mundo gráfico seguía cambiando rápidamente. Al igual que todas las personas creativas y con talento, a los desarrolladores de juegos les encantan los desafíos, y uno de la Los desafíos para ellos fueron (y seguirán siendo), durante mucho tiempo, para obtener imágenes cada vez mejores y más realistas.. 

La línea de funciones fijas proporcionó algunas características interesantes, como múltiples modos de fusión, sombreado Gouraud por vértice, efectos de niebla, búferes de plantillas (para volúmenes ocultos) y demás, por lo que los desarrolladores usaron lo que pudieron. Pronto, se produjeron algunos efectos realmente impresionantes, todos en virtud de fenómenos de la vida real simulados utilizando algunos trucos baratos (bueno, barato para los estándares de hoy). 

Todo estaba yendo muy bien, pero aún estaba limitado por la cantidad de funciones que podía hacer el canal fijo. Después de todo, el mundo real tiene muchos materiales diferentes, y para simularlos, la única variación que se les permitió realizar fue cambiar algunos modos de mezcla, agregar más texturas o ajustar los colores de reflexión de la luz.

Entonces sucedió: llegaron las primeras GPU programables. No vinieron de la noche a la mañana, por supuesto, y estaban obligados a llegar algún día, pero esto aún creaba emoción. Estas GPU tenían lo que se llamaba un tubería de renderización programable: ahora podrias escribir programas, llamados sombreadores, en un lenguaje ensamblador limitado, y haga que se ejecuten para cada vértice o fragmento, en la tarjeta de video. Este fue un gran salto adelante, y estaba mejorando.. 

Pronto, los lenguajes de ensamblaje aumentaron en complejidad y expresividad, y surgieron lenguajes de alto nivel para la programación de GPU, como HLSL, GLSL y, más tarde, Cg. Hoy tenemos sombreadores de geometría que incluso pueden transmitir nuevos vértices, o sombreadores que controlan dinámicamente la teselación y los triángulos teselados, y dentro de ellos podemos muestrear una gran cantidad de texturas, ramificar dinámicamente y hacer todo tipo de matemáticas locas en los valores de entrada.

Cuando le das a los desarrolladores estas ventajas, se vuelven locos; pronto estaban escribiendo shaders para todo tipo de cosas: mapeo de paralaje, modelos de iluminación personalizados, refracción, lo que sea. Más tarde, incluso surgieron sistemas de iluminación totalmente personalizados, como el sombreado diferido y el paso previo de la luz, y podría ver efectos complejos de posprocesamiento como la oclusión ambiental del espacio de la pantalla y la oclusión ambiental basada en el horizonte. Algunos incluso estaban "abusando" de los shaders para realizar tareas repetitivas y pesadas en matemáticas, como el procesamiento estadístico o el deshacer hashes de cadenas. (Esto fue antes de que la computación de propósito general en las GPU obtuviera soporte general). 

En resumen, los gráficos por ordenador explotaron con la introducción de sombreadores, y con una buena razón: la capacidad de programar qué sucedió exactamente en vértices, fragmentos, texturas, etc., y hacerlo. rápido, siempre casi infinitas posibilidades.

Una representación simplificada de la tubería programable. Observe cómo las etapas específicas de transformación, sombreado o textura fueron reemplazadas por sombreadores especializados. (Teselación omitida por claridad.)

El interruptor completo

Pronto, las tuberías de funciones fijas quedaron obsoletas, al menos para los desarrolladores de juegos. Después de todo, ¿por qué molestarse en estos jardines amurallados cuando puede programar con precisión lo que sucede con sus datos? Se mantuvieron en uso durante mucho más tiempo en algunas aplicaciones donde el realismo no era un problema, como en el caso de CAD. Pero en general, fueron ignorados. 

OpenGL ES 2.0, lanzado en 2007, desaprobó o eliminó su canalización de función fija a favor de una programable. OpenGL 3.2, en 2009, finalmente eliminó toda noción de vértice de función fija y procesamiento de fragmentos (sin embargo, permanece disponible para uso heredado a través de un perfil de compatibilidad). Está claro que tiene muy poco sentido hoy en día trabajar con el sistema limitado cuando tiene GPU potentes capaces de hacer cosas increíbles a su disposición.

Debido a que estas API lo obligan a usar sombreadores (y esto incluye DirectX, que, aunque no elimina explícitamente la funcionalidad, incluye herramientas para ayudar a migrar desde el enfoque anterior, y prácticamente no tiene documentación nueva con respecto al FFP), son difíciles de entender. para un principiante Si solo estás empezando como novato de la programación en 3D, es mucho más fácil decirle a la API tus matrices, parámetros de iluminación y todo eso, y haz que lo haga todo por ti.. 

Pero a largo plazo, le beneficiará mucho más si aprende a escribir programas que describan con precisión el proceso. Entenderá intrincadamente lo que está pasando bajo el capó, comprenderá algunos conceptos muy importantes que la FFP no le exige y podrá modificar sus materiales muy fácilmente para hacer algo complejo que la función fija nunca puede hacer por usted (y es útil para depurar, también!).

He mencionado OpenGL ES, y permítame desarrollarlo con más detalle. A medida que los juegos en dispositivos móviles se vuelven cada vez más populares, tiene sentido crear mundos virtuales cada vez más complejos. La mayoría de las llamadas de función fija se eliminaron en ES 2.0 (lo que, naturalmente, significa que también están ausentes en las versiones posteriores). Básicamente, esto significa que, para usar cualquiera de las funciones después de ES 1.1, necesita usar sombreadores. 

ES 2.0 es compatible con iPhones desde 3GS, iPads desde la primera versión y dispositivos iPod Touch de generación 3 y superior. Qualcomm Snapdragon, un chip ampliamente utilizado en la producción de teléfonos con Android, también es compatible con OpenGL ES 2.0. Es decir muy ancho soporte, porque ES 2.0 no es exactamente "nuevo": ya tiene más de 7 años. Aprovechar al máximo estas arquitecturas., Necesitas soltar la tubería de función fija.

Supongo que la mayoría de ustedes lo han hecho hace mucho, mucho tiempo, pero no me cuesta tanto imaginar algunos motores de gráficos 2D o juegos heredados que todavía usan funciones fijas (porque no hay necesidad de más). Todo esto está bien, pero usarlo para nuevos proyectos, o capacitar a los programadores en ellos, parece una pérdida de tiempo. Esto se ve agravado por el hecho de que muchos tutoriales que puedes encontrar en Internet están totalmente desactualizados y te enseñarán cómo usar el FFP desde el principio, y antes de que te des cuenta de lo que está pasando, estarás muy adentro..

Mi primer pincel con gráficos 3D fue un antiguo tutorial de DirectX 7 escrito en Visual Basic. En ese momento, el uso de la canalización de función fija generalmente tenía sentido, porque el hardware no estaba lo suficientemente avanzado como para lograr la misma funcionalidad con sombreadores a la misma velocidad. Pero hoy en día, vemos que las API de gráficos están empezando a disminuir o desprecian su soporte, y realmente se convierte en solo un artefacto del pasado. Es un artefacto bueno y útil que nos hace sentir nostálgicos, pero deberíamos estar alejados de él. Es viejo y ya no se usa..

Estas dulces reflexiones y refracciones de Fresnel, generadas por una demostración de OGRE (Open-source Graphics Rendering Engine), nunca se hubieran hecho si se hubiera limitado a las maneras en que los antiguos tutoriales DirectX 8 u OpenGL 1.1 aconsejan.

Conclusión

Si estás en un desarrollo de juegos serio, apegarte a la tubería de función fija es una reliquia de días pasados. Si está pensando en meterse en gráficos 3D, mi consejo (y el consejo de muchos, muchos desarrolladores) es simplemente evitarlo.. 

Si ve pasar posiciones de iluminación a la API de gráficos (no como un parámetro de sombreado), o llamadas a funciones de la API como glfogv, Corre como el viento y no mires atrás. Hay un nuevo mundo de GPUs programables por ahí, y ha existido por mucho tiempo. Cualquier otra cosa probablemente solo pierda su tiempo.

Incluso si solo te interesan los gráficos 2D, sigue siendo una buena idea no confiar más en el FFP. (Por supuesto, siempre y cuando esté de acuerdo con no admitir algún hardware antiguo). Los Shaders pueden proporcionarle algunos efectos increíbles y muy rápidos. Las imágenes borrosas, el enfoque, las cuadrículas de distorsión, la representación vectorial y la simulación a gran escala de partículas o física se pueden realizar en la GPU, y todas pueden beneficiar a los juegos 2D y 3D.. 

Entonces, nuevamente, mi consejo, incluso si no vas a aprender explícitamente sobre el desarrollo de juegos en 3D, es aprender a escribir shaders. Es divertido trabajar con ellos, y te garantizo que pasarás muchas horas divertidas perfeccionando un efecto de sombreado genial: una caja del cielo dinámica, pintura de automóviles o mapeo de sombras con división paralela, o lo que sea que tu corazón desee. Al menos eso me pasó a mí: una vez que estás acostumbrado a trabajar con la tubería fija debido a alguna limitación (como me vi obligado a hacerlo en el pasado, para obtener un rendimiento aceptable en mi 5200FX), programar la GPU es una explosión, y montones de diversión.

Espero haberles explicado a aquellos para quienes no estaba claro, cómo funcionaban los gráficos en 3D hace mucho tiempo y cómo funciona ahora, y espero haber convencido a algunos de ustedes que estaban a punto de seguir los tutoriales de NeHe o Swiftless. De lo contrario e ir a ver algo más moderno. Como siempre, podría haber cometido algunos errores, así que siéntase libre de señalarlos en los comentarios. Hasta la proxima vez!