top of page
Foto del escritorBraulio Madrid

7 Consejos de rendimiento en shaders.


Different types of materials
Different shader materials

Hasta hace poco abordamos el tema de la optimización de CPU en el tema de los 9 consejos para programadores. Ahora nos abordaremos el tema en la GPU, a diferencia de la CPU, programar en la GPU es más un lenguaje de bajo nivel algo más rústico, más arcaico y donde el paradigma al que estamos acostumbrados puede cambiar.


Los shaders son pequeños programas informáticos que corren directamente en la tarjeta gráfica y que fueron creados para representar luces y sombras o efectos de cámara, estos generalmente son de 3 tipos en unity, pero todos son parte de lo mismo.


Lo que hay que entender es que la GPU recibe la información del modelo y las texturas de la CPU, la procesa primero a través del vertex program, que permite modificar los vértices y el color de estos y luego envía el resultado al fragment program en el que le da el acabado final pintando cada pixel. Aunque hay 3 enfoques distintos en unity en el fondo sigue siendo este mismo proceso.


Fixed shader: Tipo dudoso de shader, que vendría siendo un shortcut para la persona que no se le da bien programar shaders, simplemente llenas unas pequeñas instrucciones y tienes un shader básico, pero cercena la libertad, casi nadie lo usa, y poco a poco unity esta retirando el soporte a estos shortcuts.


Shaders de superficie: vendría siendo el tipo de shader más común, es fácil de programar y básicamente solo puedes acceder a la parte de coloreado de los shaders, poco acceso tienes a los vértices, pero recargado de un montón de macros que te hacen la vida más fácil. Perfecto para ese grupo de desarrollo indie que quiere centrarse en el desarrollo del juego sin tener que preocuparse mucho del control visual o el rendimiento visual, ya que unity gestiona el como se ve y como se comporta según la plataforma de destino, pero aun así limitado.


Vertex Fragment shader: este es el tipo de shader más complejo y que ofrece mayor libertad para aquellos que sean buenos programadores hacen auténticas maravillas, aquí es donde está el santo grial de la computación gráfica y también el libro masonico oscuro para entenderlo, ya que la información es escasa y muy dispersa, los tutoriales son pocos y son algo vagos, para entenderlo tendrías que ser masón grado 33.


Image Effects: este sería por último una derivación de los shader tipo vertex Fragment que lo que hace es tomar una foto del frame actual y aplicar filtros similares a photoshop, es el humo y los espejos y es básicamente donde se posa el marketing de las consolas.


Personalmente conozco algunos trucos para la optimización de estos shaders, en general las tarjetas gráficas aplican algunas pequeñas optimizaciones como desechar la caras traseras en geometrías difusas o desechar todas las caras si no aparece en pantalla el objeto, pero controlarlo manualmente tiende a lastrar el rendimiento en vez de ganar con ello, así que dejaselo a la tarjeta gráfica el sabra que hacer. Algo genial fuera que la tarjeta gráfica desechara caras que están ocultas detrás de otras mallas pero hasta el momento no he visto algo así dentro de los shaders de unity.


  1. También tienen niveles de detalles que va desde el número 0 a hasta más de 1000, pero no conozco número mayor, siendo el número mayor el de más precisión y el menor el más rápido. Via scripts de C# puedes controlar este número ya sea de manera individual pero es costoso o de manera general, pero se siente el pico o el salto en frames y provocar que algunas cosas se vean raras.

  2. Los lenguajes de programación tienen niveles de precisión que puedes controlar y CG no es la excepción, reemplazar las entradas y salidas Float, en Fixed o Half, esto hace que los pixeles de color se calculen rápido. Pero si estas conversiones se hacen mal ocurre el efecto contrario, algo que ayuda a hacer esta labor mas rapida seria usar la etiqueta #ARB_hint_precision_fast. Ahora puedes intentar hacer esto de forma manual, la mejor manera es entender las funciones que soporta la gráfica, a veces tiene acceso a fixed desde el vertex program y no lo tiene en el fragment program, al menos puedes probar para entender que accesos tienes o buscar un plano de instrucciones de la gráfica en concreto.

  3. En móviles tratar en lo posible menor cantidad de shaders de transparencia, como lo indica el blog de shadowgun. Hay algunas soluciones baratas que sería hacer que las sombras se calculen por vértice, si los efectos de transparencia no se necesitan que sea detallados, puedes usar el canal alpha del vértice, blender no tiene soporte a este canal en vértices, pero puedes hacerlo con probuilder de unity.

  4. En efectos de imagen evitar el uso de varios efectos de imagen a la vez y más bien crear un efecto de imagen que se aproveche de un solo pase para aplicar los filtros encima o que haga una selección inteligente de este dentro del mismo shader, para esto se debe pensar que efecto es prioridad sobre otro.

  5. En shaders de vértice y superficie evitar el uso de múltiples texturas, como heightMaps, oclusión ambiental, smooth entre otros, la mayoría de las veces estas texturas suelen venir en escala de grises, por lo que perfectamente puede ir dentro de un canal aparte en una textura, lo importante y es en lo que debes devanarse los sesos es en generar un orden común o unas reglas en común dentro de tus shaders para interpretarlos. De esta forma ahorras en memoria y tu shader puede ser casi fielmente interpretado si baja de un shader level 3 a un shader level 2 o a un shader level 1.

  6. Evitar la generación de pixels en la grafica de ser posible si es el caso para los móviles, usar modelos de iluminación por vértice tanto que sea posible, aunque no lo creas se puede lograr un nivel de realismo decente, un estilo gráfico particularmente bueno, sin sacrificar rendimiento y por el contrario ganando más en detalle y vida para tu juego. Se pueden lograr muchas cosas como niebla, profundidad de color, luces y sombras, brillo especular decente, transparencia decente y hasta detalles de color a lo lejos y qué decir de la animación de vértices que aunque es un detalle caro, aun sigue siendo barato comparado con lo que puede hacer un procesador.

  7. En lo posible entreguele los cálculos ya procesados a la gráfica a través de texturas, hacer cálculos de ruido perlin para las nubes, analisis de fourier para las olas del mar o un worley celular para los reflejos cáusticos del agua, eso es simplemente un trabajo extra estúpido en juegos, esto solo vale para simulaciones realistas, de resto siempre que se pueda entregar los datos en bruto.

Está claro que quien domine a profundidad los vertex fragment shaders puede alcanzar el máximo detalle gráfico posible con el menor impacto en rendimiento, tendrá trabajo fijo dentro de la industria porque la optimización es el problema cotidiano más frecuente en los videojuegos modernos y aunque la falta de rendimiento obligue a mejorar las capacidades del hardware, también lo hace sentirnos orgullosos de que lo que hacemos rinda muy bien en una amplia gama de dispositivos de prestaciones bajas.


17 visualizaciones0 comentarios

Comments


bottom of page