Crea tu propia carta 3D

Introducción 

YRsHU-S0DKUzjSFxFsOMZbksgYce7KW5CN0NUVA_

En esta ocasión vamos a crear una Carta con un efecto 3D similar a la que vemos en el gif anterior. Para ello vamos a partir de un proyecto donde tenemos preparados los assets necesarios. Este proyecto podemos descargarlo desde aquí:

URL: https://drive.google.com/open?id=19J6lgCA-DH28lMu9dmntk1K5l3lPE66f

Una vez descargado vamos a abrirlo desde el Unity Hub. Este proyecto está creado con la versión 2019.2.9f1 asique podría ser incompatible con versiones anteriores. Una vez abierto vamos a tener una escena llamada “Sample Scene” y una serie de carpetas con los modelos,sprites,prefabs… necesarios. Además contamos con los paquetes TextMeshPro y PostProcessing que usaremos a lo largo del tutorial. Puedes acceder en todo momento a los paquetes usados a través del Package Manager. 

Preparando el proyecto

En primer lugar vamos a abrir la escena “Sample Scene” y vamos a arrastrar en ella el prefab “Hornet” dentro a la ventana de Hierarchy. Verás que aparece en rosa, eso es debido a que no tenemos aún ajustado el Render Pipeline. Vamos a empezar por ahí.

Vamos a crear una carpeta Settings donde colocaremos aquellos ajustes globales del proyecto. Siéntete libre de elegir otro nombre, yo siempre soy malisimo poniéndolos. Una vez creada vamos crear una configuración pulsando click derecho y Create/Rendering/LightweightRenderPipeline/PipelineAsets.

VGWQd4gHe2MOlUFizdKWQ6B18yOV94l98l3oMcMQ

Elige el nombre que quieras y seleccionalo para verlo en la ventana de Inspector. Aquí tenemos los ajustes del Render Pipeline. La configuración es muy intuitiva y prácticamente todo hace lo que indica. En nuestro caso solamente vamos a activar el HDR y el antialiasing. Lo demás no lo tocaremos, aunque esto va de experimentar, así que “rómpelo” a tu gusto. 

OThGO3V1Afb3n-lvqiTuoBcwG8_BfbMQ-jpYuwps

Una vez creado vamos a añadirlo a nuestro proyecto, para ello vamos a irnos a ProjectSettings/Graphics y lo colocamos en el hueco de Scriptable Render Pipeline Settings. 

Nu-fY-oOElNetX04Ou6GiYv59UrgLXO_MYTIpVBf

Hecho esto si volvemos a la escena podemos ver que el color rosa ha desaparecido. Aunque ahora se verán blanco. No te preocupes que ese será nuestro siguiente paso.

También verás que hay una luz añadida dentro del prefab de Hornet. Está configurada por mi pero llegado el punto puedes quitarla o cambiarla como quieras. 

Creación de Shaders

Vamos a darle color a nuestros objetos ahora. Como has podido ver todos los objetos están en blanco. Eso es porque nuestros shaders y materiales están por defecto. Para nuestro objetivo vamos a necesitar crear un shader con la herramienta Shader Graph. Esta ya viene por defecto en todos los proyectos que usen el Scriptable Render Pipeline nuevo. Para ello vamos a crear una nueva carpeta llamada Shaders y vamos a crear un nuevo Shader PBR (Create/Shader/PBR Graph).

ydHjBEsb-iDf6WG9kMN1gcdV-Ol-NdUIHOWcasY3

Puedes ponerle el nombre que quieras, en mi caso lo he llamado Standard_SG (ya he dicho que soy muy malo poniendo nombres). 

Vamos a seleccionarlo y abrirlo. No es el objetivo de este taller aprender a usar ShaderGraph, asique no voy a pararme en explicar el contenido, aunque como veréis es muy fácil e intuitivo lo que haremos. Crearemos las siguientes variables:

I2au9Z9_lx7BvWgiYFd2JT2NLNF6YZ_HLVkL4EaK

Conectaremos al Albedo un Sampler de una textura y la multiplicaremos por un color. Cómo veis el shader es lo más simple posible.

eZxmaaRaMuOOxbVlpGCukAVsV_9nsRnq7J5yBMg3

Haremos lo mismo en el canal de Emission para poder ajustar la emisión de algunos objetos posteriormente. 

eNdil-FYWa-YpybWE7FgidkEohHHL56aPF2CS5Qw

Pulsamos en Save arriba a la izquierda y cerramos. Ya tenemos nuestro shader creado pero tenemos un problema que veremos a continuación.

Stencil Buffers

Para obtener el efecto que buscamos tenemos que conocer el concepto de Stencil Buffer. Con ellos podemos principalmente renderizar unas partes de un objeto y descartar otras. Aquí podemos obtener más información:

https://docs.unity3d.com/Manual/SL-Stencil.html

https://www.ronja-tutorials.com/2018/08/18/stencil-buffers.html

El objetivo es mantener “invisible” un objeto y que cuando este se encuentre en la “visión” de otro objeto, se muestre. Vamos a necesitar por dos shaders:

  • Uno que leerá del stencil buffer y se dibujará solo donde el búfer tenga un valor específico, en cualquier otro lugar se descartará. 
  • Por otro, un shader que permanerá siempre invisible y que solamente mostrará aquellos valores específicos que coincidan con el stencil buffer.

Para el primer solo necesitamos añadir unas líneas, pero actualmente no es posible hacerlo a través del ShaderGraph. Por lo que vamos a realizar una transcripción del Shader Graph al código. Para esto vamos crear un nuevo Shader Unlit pero esta vez no será de ShaderGraph.

3rvtxFjAwqAa7JtOZkFqYVB_4Qjve5-3Me5x4bOM

Le ponemos de nombre Standard_StencilRead por ejemplo y lo abrimos. Mientras se abre vamos a volver al Shader Graph y vamos a realizar la copia del código del shader. Para ello nos vamos al PBR Master Node y con el botón derecho seleccionamos Copy Shader.

34kvNo49Lnrbugu4zAPBrK6hKNAQUXnM0T6rVbM5

Una vez copiado vamos a pegarlo en nuestro reciente nuevo shader unlit creado, sobreescribiendo todo lo que este tuviese. También deberás cambiar la primera línea y ponerle tu la dirección y el nombre que elegimos antes. En mi caso lo he guardado en MyShaders con el nombre Standard_StencilRead.

x0ZzHQ-tIAS1Mx3ThaFjSMDkNWVE7ipkjV-Koq_5

Ahora tenemos el mismo shader de Shader Graph pero en código para poder modificarlo. Vamos a necesitar añadir una nueva propiedad que será el valor específico del stencil. Simplemente dentro de properties al final, debajo del Color añadimos lo siguiente: 

[IntRange] _Stencil ("Stencil Value", Range(0,255))= 0

Quedando de la siguiente manera: 

9TpAMl-V5z-iL_Bo4cipeLzOnTAx0bs7hkuPGI75

Por último vamos a necesitar añadir los ajustes del Stencil debajo de los Tags antes de los diferentes pases. 

d6v6J-GxYBlbWhiJIwGwyYQkljZMqAdN1PzA8zOl

Esto hará que sólo cuando tengamos el valor de referencia, el objeto se muestre. Podemos obtener más información sobre la sintaxis y el contenido en los enlaces que anteriores. 

Ya podemos guardar el shader y volver a Unity. Tenemos preparado nuestro primer Shader. Para el segundo simplemente creamos otro shader unlit de nombre StencilWrite por ejemplo. Este estará siempre invisible y servirá para mostrar los objetos que compartan valor de referencia. Abrimos el shader y lo modificamos de la siguiente forma:

w_P9LihdepoIBpit9qSXsw6GJRtDjODbZgDMZSnR

En properties añadimos el valor de Stencil como con el anterior y eliminamos cualquier otra propiedad (normalmente textura) ya que este shader queremos que se muestre totalmente invisible. 

WaDuk-Y9U6XRTBkuTQNpGUKx6UgKpOMgBoYj9qG8

Añadimos el Stencil y le decimos que esté siempre comparando y si en algún momento el valor de referencia es el mismo, lo reemplace. 

_ucwf7uWGEQstPo3qSXb47CZkgZAdMMzMboZ0bMr

Ahora le decimos al buffer de profundidad que no se escriba (por ser un objeto que será invisible) y cambiamos el modo de Blend. Podemos obtener más y mejor información de esto aquí:

https://docs.unity3d.com/Manual/SL-Blend.html

También eliminamos todos los añadidos de Fogs por defecto de Unity y aquellas referencias a texturas que no nos interesan. Por último hacemos que la función frag devuelva siempre 0, ya que como hemos comentado esto se muestra siempre como invisible. 

Con esto tenemos todo listo para pasar al montaje de la carta. 

PD: Asegurate también de que lo tienes en la misma ruta que el anterior. Esto no es necesario, pero te facilitará encontrarlo más adelante. En mi caso al igual que antes, esta en la ruta MyShaders. 

5y6O6UbbsOBiAS15OGkqMBpYDZqFapKsCK2UAvKr

Montaje de la carta

Para empezar vamos a cambiar por fin el blanco de nuestra escena, para ello vamos a irnos a Materials/Hornet y seleccionando todo vamos a elegir nuestro Shader (en este caso el Standard_StencilRead)

Vv2Yw7d3SqVp28vkgCF3lLZ1nxRZ7hAiFHIxKcqI

Ahora tendremos que arrastrar las texturas requeridas (Main Texture y Emission Texture) si procede y establecer el MainColor en blanco (tened cuidado que el alfa no este a 0) y el EmissionColor en negro. En el caso que no tengamos texturas (como en el caso del personaje Hornet) simplemente cambiale el MainColor a tu gusto. Puedes hacerlo similar al original o ponerle tu propia versión. Así quedaría el del grass_material por ejemplo:

Q101Jo8XU0pnZqasyNIwx8SXPkYm0tnI12wL1wYw

O el dress_material, que no tendría textura:

tQKca3-eSPtB8GzYc4zYkNJrv4gzahh3LnPFnaKg

Sigue estas pautas en los demás materiales. El stencil value lo cambiaremos más adelante, de momento necesitamos ver en pantalla todo y no solo cuando este a través de nuestro “marco”.. Una vez terminado debería de quedarte algo similar a esto:

wNZf3dN38B-khdbgPSLeRCPUCXNRqdOlxWTKTtJg

Ahora vamos a crear un nuevo objeto en la escena llamado Card y lo ponemos en la posición 0,0,0. Ahora buscamos el Sprite “cover” dentro de Sprites y lo arrastramos dentro de Card. Le damos el tamaño a nuestro gusto. Este será el envoltorio de la carta. 

BnYZeNZT7fXmly2XnATtXfaM8J3QCa5yAcqO2B91

Ahora vamos a crear un Quad dentro de Card. Le ponemos de nombre StencilMask y lo colocamos en la posición 0,0,0 también. Este será nuestro marco a través del que se verá nuestra Hornet. Para poder ajustarlo vamos a tener que configurar ya el valor de referencia del stencil así como crear un nuevo material StencilWrite para nuestro quad recién creado. Vamos a empezar por esto último, crearemos un nuevo material con el shader StencilWrite. Lo colocamos dentro de Materials para tenerlo ordenado. A este material le vamos a poner en el valor de Stencil el valor 2 por ejemplo. Es simplemente un valor referencia, mientras tanto el receptor como el emisor tengan el mismo, funcionará. 

h4Ka8FwEHcwXvk2pZ_OGqySSWnzjytaaI1qLs9Mg

Una vez configurado vamos a arrastrarlo al StencilMask (o cambiamos el material dentro de MeshRenderer) para colocarselo. Veréis que se ha vuelto invisible, eso es que funciona como debería. Por último vamos a irnos a los materiales StencilRead que configuramos anteriormente y vamos a ponerles el mismo valor de referencia al Stencil. Seleccionamos todos o uno a uno y en Stencil Value le colocamos 2. 

-MWpeTJOE8_0k1lbL-AvZ650EBvS-2zuupUj7EFQ

Ahora debería de volverse todo invisible en la escena quedando solo la carta en negro. Vamos a desactivar de momento la carta llamada “cover” (o el nombre que tu le hayas puesto) de la ventana de Hierarchy. No se ve nada pero no es un error. Ahora mismo todos los shaders tienen el mismo Render Queue por lo que nuestro efecto no está funcionando.  Más información de esto aquí:

https://docs.unity3d.com/Manual/SL-SubShaderTags.html

 Sabiendo esto solamente tendremos que asegurarnos que nuestro StencilWrite se renderice antes. Vamos a nuestro material y le restamos 1 al RenderQueue.

H6q37hAZV1getIniyRaYFVpLE64r2Nxa50zboAnE

Con esto ya deberiamos tener visible nuestro modelo únicamente cuando estemos viendolo a través de nuestro quad. 

9l1sz4JDQnU5tIYLhAk0i3I9ZO__qqL78v-yQCR9

Ahora volvemos a activar el cover para ajustar la carta y el hueco como queramos. Al activarlo verás que tapa la visión a través del quad. No te preocupes, simplemente ve a los ajustes del SpriteRenderer del cover y cambia el MaskInteraction a Visible Outside Mask. 

ZUaOd8tg2wXN3gEO-_XjHnslFNc_GqN0h3S99un_

Ahora ajustamos el Quad hasta tener el tamaño que deseemos. Una vez confirmado podemos probar a girar en la escena alrededor de la carta para comprobar el efecto. 

5iTGxUXzhTYEm32mbLq50kZ-8eY45QaenSw3vuBo

Para organizar mejor la escena vamos a colocar el objeto Hornet dentro de Card y vamos a crear un prefab para tenerlo guardado. Gracias a los Nested Prefab ya podemos hacer prefabs dentro de prefabs, asique nos viene genial.  

Ahora solo nos falta añadirle algo de texto. Vamos a usar TextMeshPro para esto. Pulsamos botón derecho y creamos un nuevo texto en 3D. 

EQM2uvHL6g1yFOT7SU08MSV6UlBFnRuxGXlhbnyV

Vamos a empezar por el nombre de la carta, por lo que le ponemos de nombre al text “Name” por ejemplo. Vamos a escribir el texto del nombre en el apartado Text y vamos mover y escalar el objeto colocándolo donde más nos guste. En mi caso he decidido ponerlo arriba. 

2kY_qMpx24P9Wh1exUZnb4rrLN5TC9FVhllR5Tkp

Vereis que no se ve cuando lo colocamos en la zona de la carta. Eso es por el orden de renderizado que tienen. Vamos a abrir los ajustes extra del texto (extra settings) y vamos a subirle el orden in layer a 1. 

5QF5cB5d9XKykxVlr6LEPZknW9LSHfemNBLFnatO

Con esto conseguimos verlo, pero existe un problema, que el texto aparece también por detrás. Esto lo solucionaremos más adelante ya que tendremos que añadir un script simple para que active el culling. 

Llegados a este punto me he dado cuenta de que la carta está colocada del revés y el nombre por la parte trasera se ve invertido. En nuestro caso podemos solucionarlo rápido ya por delante la carta no se ve afectada. Simplemente nos vamos al objeto “cover” y marcamos Flip X. De esta forma la parte de atrás estará perfecta.  

62eHFdt2fgEpI6fKZ9g1sw0qxlkyUdBlz-MM4okd

En el caso de que tuvieras una imagen diferente deberías tener cuidado ya que la carta es la misma tanto en la partal como en la dorsal. Todo se dará la vuelta. Si quieres tener un control más exacto, deberás tener una carta delantera y otra trasera, cada una con su ajustes (y quizás optimizada para no pintar dos cada cara). 

Vamos a guardar el avance, aplicamos el prefab y guardamos escena. Deberíamos tener algo similar en estos momentos:

NUUdrpUiHPyvNQ7_9Boy20G73MpIIZ-QH2xQnCKe

Vamos a crear ahora otro texto para colocarlo en la parte de debajo. Duplicamos el objeto Name con Control+D y cambiamos el nombre a Description. Movemos el objeto a nuestro gusto, en mi caso lo coloque en la parte de abajo, centrado. Puedes tocar los ajustes del TextMesh que son maravillosos, sobre todo si has trabajado con el deprecado Text. 

Si queremos podemos cambiar la fuente. Para ello simplemente tendrás que descargarla de internet (o obtenerla de otra forma) y meterla dentro de Unity. Una vez dentro no es simplemente arrastrarla. Para poder usarla en TextMesh necesitarás crear un atlas de la fuente. Pero es fácil de hacer, simplemente abre la ventana Font Asset Creator desde WIndows/TextMeshPro.

3i738yh9jQi1g6JZrgvoDd4mzqdtYK_gHeBQeSWz

Selecciona la fuente y pulsa Generate Font Atlas (si quieres cambiar algún otro ajuste puedes hacerlo, pero ten cuidado. Más información sobre esto aquí: http://digitalnativestudios.com/textmeshpro/docs/font/ ) 

Una vez generada simplemente guárdala donde quieras y luego colócala en el texto dentro de Main Settings:

QWt4NdFKGLlDCIIsqNLMXsGtrce-zyEJPtkr1qw4

Una vez tengamos la descripción vamos a guardar el prefab y a colocar los Post Procesos. Para ello Vamos a ir a la cámara y vamos a asegurarnos que tiene añadido un Post Process Layer. Esto es imprescindible para poder continuar. También vamos a activar a antialiasing FXAA y vamos a crear un nuevo layer PostProcessing para posteriormente usarlo en el Volume. 

Y8VTBRjZpdxT17htMTyZZfEI1Qg1JCIoacgM0t5j

Ahora vamos a crear un nuevo objeto en la escena. Le vamos a añadir el componente Post Process Volume. Vamos a marcar IsGlobal porque solo tendremos este para toda la escena y vamos a seleccionar un profile. En nuestro caso no tenemos ninguno creado, asique le daremos a New.

u7XSTQWl66O4EsM8M4g5UqYpVbdlKfyqLI-vmWtP

Ahora simplemente asegurate de que este objeto está en el Layer PostProcessing

bRfRtoJ5t4sCrrmpRjyunNBbR5vY9N13a07DsIBR

De otra forma no funcionará y no podremos ver ningún cambio. 

Una vez configurado podremos ir añadiendo efectos ya creados por Unity o crear los nuestros propios. En este caso vamos a usar dos creados, el Bloom y el Color Grading. Pulsamos en Add Effect y seleccionamos uno y después el otro. 

KQaT79FwVdK0ZTzM_sN3e94V5d3g8eOPXsh4zA5J

Aquí puedes sacar tu lado artístico y elegir la configuración que más te guste. En mi caso después de una serie de pruebas quedó así:

IQzUyxWAP3IX57WQzyQ4aRJVYYVebNgqvhh85v_f
Czd2POCYdr5nTGWdE9mZ3UN-DOc7QzKnHMixttrC

En este punto deberías tener algo similar a esto. Si no es así asegúrate de que el material del lazo tiene un emission color bien configurado. 

OYGPtLhLpuFSx1s-ob6St4kObox-hF7nxFsuNXS2

Por último nos queda solucionar el error del texto por ambas caras. Para eso simplemente vamos a crear un script con el nombre CullingTextMeshPro o el que querais y vamos a dejar solo la función Awake con el siguiente código:

LNvyxmrc9qHOWIFilgz4pVgiu1D1opjX6TS9f5te

De esta forma al darle al Play el texto automáticamente hará culling y no se renderiza por detrás. Estuve informándome sobre otras formas de hacer esto, pero las respuesta de Unity fueron que esta era la forma. Pero si conocéis otra forma contactad conmigo y lo actualizo.

Espero que os haya gustado y hayáis aprendido cosas nuevas que al final es el objetivo esto.

Hasta pronto!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *