Galaxy Skin Shader Featured Image

Galaxy Skin Shader Breakdown – Parte 1

Recientemente me puse un poco Fortnitesco (o algo así) y decidí construir mi propia versión de una Galaxy Skin. En este post dedicado a shaders con Unreal Engine, voy a mostrar como construir y replicar el siguiente efecto:

Galaxy Skin Shader – Unreal Engine

Construyendo el shader

Comenzaremos por construir nuestro shader. Para esta versión en particular, decidí optar por una combinación de distintos efectos.

La configuración utilizada para nuestro material es:

  • Material Domain: Surface
  • Blend Mode: Opaque
  • Shading Model: Unlit

Depth Texture Reflection

Esta sección de nuestro shader hace referencia a la visualización de la textura y al efecto de “profundidad estática” que genera en nuestro modelo 3D.

Utilicé una textura de nebulosa convincente (puedes utilizar cualquier textura que gustes) y la convertí en una textura seamless con la ayuda de GIMP.

Así es como luce la primera parte de nuestro shader:

Depth Texture Reflection Node Section
Depth Texture Reflection – Unreal Engine

El nodo Reflection Vector es un nodo de Unreal Engine que nos devuelve el vector de reflexión de nuestro punto de vista/cámara. Para entenderlo mejor, demos un vistazo al siguiente gráfico ilustrativo:

Reflection Vector Logic

En esta representación podemos observar como es que trabaja un vector de reflexión, donde d es el vector de incidencia (punto de vista/cámara), n es la normal de la superficie, r es el vector de reflexión y t el vector de transmisión.

Para mapear texturas sobre objetos 3D solo necesitamos dos vectores, así que utilizamos un nodo Component Mask para obtener los vectores RG de nuestro Reflection Vector y los utilizamos como mapeo de UV sobre nuestra textura.

Esto debería ser suficiente para crear nuestro efecto, pero hay un detalle particular en este shader. Este método funciona bien cuando la textura utilizada es de tipo Cube Map y están especialmente diseñadas para Skybox.

Seguro habrás notado que hay un nodo Vector3 con valores 0.5 para cada componente como dato de entrada para nuestro Reflection Vector.

Ya que no estoy haciendo uso de un Cube Map, sino de una textura seamless, este nodo ayuda a personalizar la Custom World Normal. Esto me permite modificar la posición de la textura y evitar que se deforme, estrechandoce o estirandose.

Sí previsualizamos nuestro resultado obtendríamos algo como esto:

Depth Texture Reflection Preview
Depth Texture Reflection Preview – Unreal Engine

Fresnel Function

Este efecto (como muchos otros) se ve mejor con una función de Fresnel aplicada. Esto le da un mejor y más vistoso detalle al resultado final.

Fresnel Function Node Section
Fresnel Function – Unreal engine

Utilizando un nodo Fresnel con un parámetro Fresnel Multiplier que nos permita controlar la influencia exponencial de nuestro efecto y un nodo de función Cheap Contrast conectado a un parámetro que regule el contraste, vamos a lograr un efecto similar a este:

Fresnel Function Preview
Fresnel Function Preview – Unreal Engine

Fresnel Color

En esta sección vamos a agregar color a nuestro efecto Fresnel anterior.

Fresnel Color Node Section
Fresnel Color – Unreal Engine

Este apartado es realmente sencillo. Utilizamos un parámetro Vector3 para designar un color (a nuestro gusto) y lo multiplicamos por un parámetro Glow Crank para controlar la intensidad del color.

Base Color Shadow

Vamos a agregar un detalle de sombra a nuestro efecto. Esto le dará un feeling de profundidad sobre el color final a todo el conjunto.

Base Color Shadow – Unreal Engine

Vamos a aplicar una sombra vertical a nuestro modelo utilizando la componente V (G con Component Mask) de nuestro nodo Tex Coord. La invertiremos para que su dirección sea de abajo hacia arriba.

Con un nodo Power conectado a un parámetro Ambient Shadow vamos a controlar la intensidad exponencial de nuestro efecto de sombra. Al final multiplicaremos el resultado por la textura Depth Texture Reflection.

El resultado debería verse similar a esto:

Ambient Shadow Preview
Ambient Shadow Preview – Unreal Engine

Preview General 1

Vamos a dar un vistazo general a nuestro avance hasta ahora. Con un nodo Lerp vamos a unificar nuestras secciones construidas.

Lerp Union Node
Lerp Node – Unreal Engine

Conectando la multiplicación de la sección Ambient Shadow con Depth Texture Reflection al pin A, la sección Fresnel Color al pin B y la sección Fresnel Function al pin Alpha obtendremos el siguiente resultado:

General Preview 1
General Preview – Unreal Engine

Main Stars Layer

En esta sección vamos a agregar los detalles interesantes del shader como lo es la capa de estrellas personalizada.

Main Stars Layer Node Section
Main Stars Layer – Unreal Engine

Aunque el grafo parezca complejo a simple vista, realmente es muy sencillo de entender.

La primera parte se encarga de aplicar un efecto tiling sobre nuestra textura de estrellas, multiplicando las componentes UV de nuestro nodo Tex Coord.

Main Stars Layer Tiling
Main Stars Layer Tiling – Unreal Engine

La segunda parte aplica un efecto offset sobre nuestra textura, con un nodo Panner controlado por dos parámetros de movimiento.

Main Stars Layer Offset
Main Stars Layer Offset – Unreal Engine

Por último, con un nodo Subtract controlado por un parámetro llamado Main Stars Amount Offset controlaremos la “cantidad de estrellas” en el layer. Al final el resultado es conectado a un nodo Saturate para anclar los valores entre 0 y 1.

Main Stars Layer Amount
Main Stars Layer Amount – Unreal Engine

Para entenderlo mejor, Subtract se encargará de restar el valor de Main Stars Amount Offset al valor de la textura de estrellas. Esto hace que los valores más pequeños disminuyan o desaparezcan (se vuelvan 0) en el layer de estrellas, creando el efecto de reducción.

Volumetric Depth Stars

Ahora vamos a agregar una nueva capa de estrellas, con la diferencia de que esta sección añadirá un efecto de profundidad volumétrica.

Volumetric Depth Stars Node Section
Volumetric Depth Stars – Unreal Engine

Vamos a fragmentar esta sección para poder explicarla mejor.

Custom Reflection Vector
Tangent Space Reflection Vector
Tangent Space Reflection Vector – Unreal Engine

Vamos a utilizar un nodo Camera Vector y transformaremos su espacio de World Space a Tangent Space con Transform Vector. En otras palabras, nos aseguraremos de que este efecto se renderice en espacio de tangente.

Conectaremos un nodo Vector3 con valor 0, 0, 1 al pin Normal del nodo Custom Reflection Vector y nuestro transform anterior al pin Camera Vector.

Esta secuencia de nodos nos permite obtener un vector de reflexión personalizado. El nodo Vector3 indica que el efecto se aplicará de forma perpendicular a la geometría.

En términos simples, el efecto de profundidad ocurrirá a lo largo de la normal de la geometría, sin distorsiones verticales u horizontales.

Depth Offset
Depth Offset
Depth Offset – Unreal Engine

Esta sección se encarga de controlar el offset o distancia de profundidad de la capa de estrellas.

Con Component Mask obtenemos la componente B de nuestro Custom Reflection Vector y a continuación obtenemos su valor absoluto Abs para evitar valores negativos. Dividimos el resultado por la distancia de profundidad que deseamos, en mi caso utilicé un valor fijo de 512.

Multiplicamos el resultado de la división anterior por los componentes RG de nuestro Custom Reflection Vector.

Depth Resolution Offset
Depth Resolution Offset
Depth Resolution Offset – Unreal Engine

Este conjunto de nodos se encarga de controlar la cantidad de offset de profundidad que ocurre con base en la resolución de la textura que utilizamos.

En este caso el valor de resolución de la textura es de 1024. Dividimos este valor por 1. El resultado lo multiplicamos por nuestro anterior Depth Offset.

Offset Panner
Offset Panner
Offset Panner – Unreal Engine

Finalmente, conectamos nuestra operación anterior a un nodo Add. En el segundo pin de entrada agregamos el nodo Panner desde nuestra sección Main Stars Layer.

Por último, al igual que en nuestra sección Main Stars Layer, hacemos un Subtract controlado por un parámetro Depth Stars Amount Offset para controlar la cantidad de estrellas. Conectamos un nodo Saturate para hacer clamp de los valores y listo.

Stars Color

Para la última sección de nuestro shader vamos a aplicar color a nuestras estrellas.

Stars Color Node Section
Stars Color – Unreal engine

Vamos a comenzar con un Lerp que nos permita colorear nuestras estrellas de tonos bicolores basados en una textura de noise simple. El color de nuestras estrellas se basará en el valor 0 o 1 de nuestra textura noise.

Stars Color Lerp
Stars Color Lerp – Unreal engine

El nodo Lerp anterior lo conectaremos a un segundo Lerp en el pin B, mientras que el pin A tendrá un valor fijo de 0. Su pin Alpha recibirá el nodo Saturate de nuestra sección Main Stars Layer.

Repetiremos la acción anterior con un tercer Lerp, pero en esta ocasión el pin Alpha recibirá el nodo Saturate de la sección Volumetric Depth Stars.

Stars Color Lerp Nodes
Stars Color Lerp Nodes – Unreal engine

A continuación, vamos a multiplicar el resultado del segundo y tercer Lerp por un parámetro Stars Glow Multiplier que controle la intensidad del brillo de nuestras estrellas.

Finalmente, con un nodo Add uniremos estas dos capas de estrellas desde sus nodos Multiply.

Stars Color Add
Stars Color Add – Unreal engine

Ajuste Final

Como último paso y finalizando el shader, vamos a conectar nuestro nodo Add de la sección Stars Color con un nuevo nodo Add.

Este nuevo nodo Add debe ser un nodo intermedio al cual conectaremos nuestra textura de la sección Depth Texture Reflection como entrada. Acto seguido conectaremos la salida del nuevo Add al nodo Multiply de la sección Base Color Shadow.

Final Step Add Node
Final Step Add Node – Unreal Engine

Preview Finalizado

Este es el resultado de nuestro shader:

Final Preview
Final Preview – Unreal Engine

Al acercarte a la geometría podrás apreciar la capa de estrellas con efecto de profundidad:

Depth Stars Preview
Depth Stars Preview – Unreal Engine

Con algunos ajustes de Post Procesado como el efecto Bloom y agregando detalles extra como partículas con Niagara puedes obtener un resultado así:

Galaxy Skin
Galaxy Skin – Unreal Engine

Actualización y mejoras

Analizando el shader y realizando algunos experimentos, me he dado cuenta de algunas mejoras que se pueden llevar a cabo.

Ambient Shadow per Object Position

El problema

En la primera sección de nuestro shader aplicamos un efecto de sombra en degradado vertical. Este efecto ayuda a crear más profundidad visual:

Base Color Shadow – Unreal Engine
Ambient Shadow Preview
Ambient Shadow Preview – Unreal Engine

El problema con esta solución es que el degradado ocurre en los UV Maps. Si utilizamos un modelo con un mapeado diferente al del Mannequin estándar de Unrel Engine, ocurriría algo así:

Ambient Shadow UV Issue
Ambient Shadow UV Issue – Unreal Engine
Solución

Para resolver esto vamos a aplicar el efecto sombra en Object Space.

Object Space Shadow Node Section
Object Space Shadow – Unreal Engine

El nodo Local Position es una Material Function que se encarga de transformar el Absolute World Space a Local Space. Con esto nos aseguramos de que el efecto comienza en el origen del modelo 3D.

Con una operación Subtract controlada por un parámetro Gradient Mask Offset vamos a poder controlar el offset u “origen” de nuestro efecto. Para aplicar el efecto verticalmente a nuestro objeto, necesitamos un Component Mask aislando la componente B.

La siguiente imagen muestra como se vería nuestro modelo con un offset de 100 unidades (cm en Unreal Engine) aplicado. Recordemos que el origen de este modelo se encuentra en la base del mismo, a la altura de los pies.

Local Space Offset Preview
Local Space Offset Preview – Unreal Engine

Vamos a conectar la operación anterior a un nodo Divide controlado por un parámetro Gradient Mask Falloff. Este parámetro nos permite controlar la atenuación de nuestro gradiente, de esta forma podemos configurar la “longitud de su caída” a nuestro gusto:

Local Space Falloff Preview
Local Space Falloff Preview – Unreal Engine

Con el error corregido lo único que nos queda por hacer es habilitar ambas opciones para los usuarios: sombra por UV Maps o por Object Space. Para ello utilizamos un nodo Static Bool Param conectado a un nodo Static Switch.

Como valor true conectamos nuestro nodo Divide anterior. Como valor false conectamos nuestro nodo One Minus de la versión UV Maps. El resultado lo conectamos al nodo Power que persiste desde la versión original.

Static Bool and Switch Conditional
Static Bool and Switch Conditional – Unreal Engine

Ahora nuestro efecto está corregido y listo para utilizarse en modelos externos.

Ambient Shadow Local Space Preview
Ambient Shadow Local Space Preview – Unreal Engine

Reorganización del Stars Layer

El problema

Ya sea con UV Maps o con Local Space, el efecto sombra del shader nos deja con otro problema a resolver. Entre mas amplio sea el valor de Ambient Shadow mas intenso se vuelve el efecto.

Si subimos los valores tanto de Ambient Shadow como de Offset o Falloff, nuestra sombra comienza cubrir las estrellas hasta desaparecerlas:

Stars Fade Preview
Stars Fade Preview – Unreal Engine
Solución

Para corregir este detalle basta con reorganizar un nodo y sus conexiones. Concretamente, se trata del nodo Add que se encarga de combinar las capas de estrellas con la base del shader.

New Add Node Route
New Add Node Route – Unreal Engine

Comenzamos reconectando nuestra textura de nebulosa al nodo Multiply encargado del efecto sombra. Este último nodo lo pasamos como entrada al nodo Add y a su vez, la salida al nodo Lerp final.

Esta configuración permite que la textura de profundidad y la sombra se apliquen en conjunto, previo a aplicar el layer de estrellas. Una vez esto ocurre, aplicamos el layer de estrellas sobre esta capa de información. De esta forma, nuestro layer queda por encima del efecto sombra, viéndose así:

Stars Overlay Preview
Stars Overlay Preview – Unreal Engine

Implementar o no la solución queda a cargo de la visión artística del usuario, no es obligatoria.

Siguientes Pasos

Quiero ofrecer agradecimientos especiales a:

Ya que gracias a sus tutoriales, recursos y conocimientos he podido recrear este shader inspirado en Fortnite.

Ahora es tu turno para recrear este shader y hacer improvements sobre él. ¿Sabías que puedes cambiar el modelo de shading para que reaccione a la luz? O quizá prefieras intentar utilizar una textura de Cube Map para la nebulosa.

En el siguiente post: ¿cómo crear el efecto de partículas de este shader con Niagara y Unreal Engine 5?

Si tienes alguna duda o pregunta no olvides dejar tu comentario para que todos podamos aportar y aprender.

Sigue aprendiendo sobre VFX para videojuegos en este post y continúa practicando una y otra vez hasta ser un experto.

Leave a Reply

Your email address will not be published. Required fields are marked *