¿Qué es el stencil buffer? 

Así como existen el color buffer y el Z-Buffer, éste contiene información extra normalmente guardando valores enteros y es usado comúnmente para delimitar el área de 'rendering' de ciertos objetos en pantalla e indicar las condiciones bajo las cuales se van a pintar.

Tiene muchos usos avanzados en VFX pero en este artículo veremos un ejemplo muy sencillo de como utilizarlo con shaders de Unity.


REQUERIMENTOS

  • Funciona con cualquier Render Pipeline, en mi caso utilizare URP. 
  • Conocimiento básico de programación de shaders en HLSL.
  • Conocimiento básico de Unity.
  • En mi caso, estoy utilizando Unity 2020.3 pero debería funcionar en otras versiones sin problema.


EJERCICIO

Desarrollaremos una máscara usando shaders que nos permitirán pintar en pantalla los objetos únicamente cuando se encuentren en la posición correcta en relación a nuestra máscara. 


SINTAXIS 

Para esto, debemos utilizar dos shaders distintos, uno para el objeto 'máscara' y otro para el objeto que se va a pintar únicamente en la silueta de la misma. 

Voy a crear dos 'Unlit Shader' distintos para este ejemplo, uno para la máscara y otro para el objeto a enmascarar. 

Escribiremos el siguiente código en el campo del 'SubShader' y antes del 'pass', recuerda que son dos shaders distintos. 



  • ref: Un entero que se asigna al shader que el buffer leerá y podrá comparar con otros shaders para saber como comportarse. Estos enteros pueden ir desde 0 a 255.
  • comp: La operación de comparación que debe hacer para saber si el objeto se renderiza o no. De ser exitosa la comparación se ejecutara el 'pass' y por ello el 'fragment output'.  
  • pass: Esta sección indica que hacer con el número de referencia en relación con el stencil buffer, en este caso usamos 'replace', 'este escribirá el número de referencia en nuestro stencil buffer. 


-'equal' Se refiere a que los pixeles van a pintarse en pantalla cuando el valor de referencia sea el mismo en el stencil buffer que en el shader (en este caso 1) 

-'always' Se refiere a que los pixeles del objeto que tenga este shader siempre se van a pintar en pantalla. 


A continuación, vamos a crear un plano y una esfera como objetos de prueba, posicionaremos la esfera por delante del plano

Creamos dos materiales a partir de los dos shaders que acabamos de escribir, asignamos la máscara al plano (este va a delimitar el área de rendering de nuestra esfera), y asignaremos el otro material a la esfera.

Podemos ver ahora como nuestro plano está actuando como máscara limitando el área donde nuestra esfera se está pintando en pantalla. 

Esto sucede debido a que el plano está sustituyendo el valor dentro del stencil buffer a 1, y en el shader de la esfera le estamos indicando que solo se va a ejecutar el 'pass' de su shader (y con esto su fragment output) solo si al comparar las referencias en el stencil buffer éste es igual a 1. 


NOTA: Es posible que al momento de asignar los materiales la esfera o el plano parpadeen o desaparezcan de repente, para resolver esto, basta con aumentar +1 al render queue del material de la esfera, esto es para informarle al z-buffer que ésta debe pintarse frente al plano, de otra manera estarán compitiendo por el mismo espacio dentro del buffer. 




EXTRAS

En muchas ocasiones no queremos que nuestra máscara tenga color alguno, hacer esto es muy sencillo, simplemente agregaremos una línea 'ColorMask 0' en el campo del SubShader, esto detiene al shader de escribir en cualquiera de los canales de color RGBA, por lo que nuestra máscara tendrá el mismo funcionamiento pero sin color alguno.



¿Pero qué pasa si queremos que nuestra máscara vaya delante del objeto a enmascarar? ahora mismo nuestra máscara solo funciona si está detrás de este objeto, esto es porque ambos objetos son de tipo 'Opaque' y si la máscara estuviera antes de la esfera, nuestro buffer no podría ver la esfera y por lo tanto no la registraría, es decir, no habría forma de comparar los valores de referencia de nuestros shaders.

Para solucionar esto, basta con agregar una línea en nuestro SubShader que dicta 'ZWrite Off' para habilitar la transparencia en nuestro material, permitiendo ver ahora ambos objetos. 
También cambiaremos el 'RenderType' a 'Transparent'. 



Ahora nuestra máscara funciona frente y detrás de nuestro objeto.



Ahora puedes dar uso de las máscaras para crear VFX interesantes o añadirlos como mecánica a tu juego. Yo hice una carta de un gato para poner a prueba esta clase de shaders.




DESCARGAR

Si te interesa descargar directamente los shaders y una escena de muestra, puedes hacerlo aquí:


Estás en completa libertad de usarlo para cualquier fin una vez adquirido. 


Para cualquier duda o aclaración, házmelo saber en los comentarios o ponte en contacto directo conmigo aquí. De igual manera, si deseas contribuir a la página puedes hacerlo mediante mi cuenta en Ko-fi:


Comentarios

Publicar un comentario