Jump to content

Search the Community

Showing results for tags 'shader'.



More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • General
    • Proyectos
    • Offtopic
    • Unity Feeds
    • Website
    • Youtube
  • Mesa de ayuda
    • Unity
    • Arte
    • Builds & Dispositivos
    • Otras Especialidades
  • Aportes de la Comunidad
    • Recursos
    • Eventos
  • Bolsa de trabajo & Colaboraciones
    • Ofertas y Demandas

Blogs

There are no results to display.

There are no results to display.


Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Especialidad

Found 4 results

  1. Esta es la primera vez que hago un post en esta página, así que no me deja ir a cualquier sección a publicar (solo estoy limitado a publicar en offtopic). Espero en verdad recibir una respuesta, ya que en ningún sitio de habla inglesa e recibido alguna. Aparentemente es un tema complicado (?), o al menos no encontré nada al respecto en inglés, así que veré si aquí tengo suerte... Tal y como lo dice el título, se trata de un problema que al parecer es muy común en Unity. Básicamente, en una escena totalmente oscura, en la que haya árboles (o cualquier otra vegetación creada con Tree Creator), una spotlight causará que la vegetación que esté "cerca" de la vista del jugador, comience a brillar, como si hubieramos configurado el shader como unlit. He intentado cambiar el shader (he usado el Standard, Legacy y el que usualmente me solicita, Tree Creator), y nada ha hecho un cambio. Este problema solo ocurre con las spotlights, no con otros tipos de luz. Estoy trabajando en Unity 5.6, en una máquina x64. Adjunte una imagen de una de mis escenas, en la que está ocurriendo el problema.
  2. Buenas noches! Tengo un problemilla intentando cambiar una propiedad de un material. Estoy usando un componente TextMeshPro, y hay una propiedad (_LightAngle) que quiero cambiar en runtime. Estoy haciendo issueText.material.SetFloat(ShaderUtilities.ID_LightAngle, lightAngleStep); en un Update(). (obviamente estoy cambiando lightAngleStep en cada iteración, y la referencia al componente de texto es correcta). He probado, por si acaso, a llamar a la otra sobrecarga del método pasando directamente el nombre del parámetro en lugar de su identificador ("_LightAngle"), pero el resultado es el mismo. Lo que quiero es cambiar el ángulo desde el que le afecta la luz para darle un poco de sensación de movimiento al texto. Adjunto capturas. No sé si es que está pasando algo, o es que no es la forma de hacer lo que quiero. Se aceptan ideas 😁
  3. En esta entrada vamos a aprender a crear nuestro primer shader Vertex/Fragment en Unity. Iremos paso a paso hasta terminar creando nuestra propia bandera con ondulación: Requisitos Para crear este proyecto podemos usar cualquier versión de Unity 2018/2019/2020 siempre y cuando a la hora de crear el proyecto usemos la plantilla de 3D (Built-in Render Pipeline) Antes de pasar al código, creo que es necesario que definamos qué es un shader y las partes que lo componen. ¿Que es un Shader? Un shader es un contenedor de instrucciones que se envían a la GPU para mostrar los elementos que tenemos en pantalla. Al igual que el script de un personaje contiene las instrucciones para que este se mueva o gire, el shader contiene información sobre el color o los vértices de un objeto. Al igual que para escribir comportamientos Unity usa C#, para escribir shaders Unity usa su lenguaje llamado Shaderlab. A su vez Shaderlab permite escribir fragmentos de código en CG (C for Graphics) que es donde realmente estará el código del shader en sí. El lenguaje CG fue desarrollado por Nvidia y Microsoft y es compatible tanto con OpenGL como con DirectX. Veremos más adelante en profundidad las partes que componen Shaderlab y CG. Tipos de Shaders En Unity tenemos dos opciones a la hora de crear un shader. Surface shaders: podemos definirlo como una "plantilla" creada por Unity para facilitarnos gran parte del trabajo aunque dando menos control sobre el resultado final. Vertex/Fragment shaders: el código que existe bajo la capa de Surface anterior. Tiene mayor complejidad pero ofrece mayor control sobre el resultado. En esta entrada nos centraremos en estos últimos, ya que el paso a Surface (o a ShaderGraph) es mucho más productiva si conocemos los conceptos del Vertex/Fragment. Fases del Pipeline Para conseguir mostrar un objeto de juego (3D) por pantalla (2D) se requiere de un proceso con varias fases. Ese proceso es llamado Rendering Pipeline. Para que sea más sencillo de entender, voy a resumir los pasos para centrarnos en los que nos interesa ahora. Básicamente tenemos dos funciones que podemos modificar: Vertex: En esta función podemos modificar datos relativos al mesh, principalmente la posición de los vértices, de ahí su nombre. Consta de una entrada de datos (como la posición de los vértices mencionada o las uvs) y produce una salida que será el input de la función fragment. Fragment: En esta función obtenemos los datos recibidos después de convertir las coordenadas del objeto en coordenadas de pantalla. Por ello todas las modificaciones aquí son a nivel de coordenadas de pantalla. Por ejemplo el color, su transparencia etc. Esta explicación es muy superficial y muy rápida, puedes encontrar más información aquí: https://en.wikipedia.org/wiki/Graphics_pipeline Una vez explicado esto, vamos a pasar a la parte práctica. Abrimos por fin Unity y creamos el proyecto con la plantilla de 3D que comentamos (Built-in Render Pipeline). Partes de un Shader en Unity Para empezar vamos a crear una nueva escena. La abrimos y creamos un nuevo Shader Unlit: Le ponemos de nombre FlagEffect por ejemplo y creamos un Material que lo use. Ahora crearemos un cubo en la escena y le colocamos las siguiente posición, rotación y escala: Creamos ahora un Plano, le arrastramos nuestro material y lo colocamos en: Si todo ha ido bien deberás tener algo así. Puedes ajustarlo tú a tu gusto (aunque ten cuidado al girarlo ya que podrías no tener el resultado esperado al final) Una vez creada nuestra bandera, vamos a abrir el shader FlagEffect. Vamos a borrar todo el contenido y vamos a ir conociendo sus partes poco a poco. Esta sería la estructura del shader con la que deberías empezar: Shader: La carpeta donde se registrará nuestro shader. Properties: Son las variables que podemos crear y ver a través del inspector del material. Cuando en un inspector ves una cajita para la textura, un botón para el color o un campo con un valor numérico aquí es donde se deben crear. La sintaxis es la siguiente: NombreVar ("TextoInspector",TipoVariable) = ValorPorDefecto Aquí podemos ver las diferentes propiedades que podemos crear en Unity: https://docs.unity3d.com/Manual/SL-Properties.html SubShader: El contenido del shader estará aquí dentro. Pass: Cada llamada de pintado que haremos. Cada una tendrá sus funciones Vertex y Fragment. Por defecto solo tendremos y necesitaremos una. Aquí es donde estará el código, acotado entre la pauta de inicio y de fin de CG que vemos en la imagen. Fallback: no es obligatorio aunque es recomendable. Si nuestro shader no es compatible con la plataforma en la que corra, se llamará a otro shader para evitar que se vea rosa. Pero para nuestras pruebas recomiendo borrar la línea. De esta forma si tenemos algún problema con nuestro shader podremos verlo directamente (de otra forma puede que llame al Fallback y no lo veamos rosa). Una vez tenemos la plantilla básica, vamos a añadir las funciones de Vertex y Fragment y los input/output necesarios. Vamos a empezar creando estos últimos. Como vimos anteriormente vamos a necesitar una entrada a la función Vertex y una salida de ella. También necesitamos una salida de la función fragment. Para esto usaremos struct de C (que se declaran igual que en C#). Ahora vamos a necesitar las funciones Vertex y Fragment. La primera tendrá como parámetro su input y devolverá el output. La Fragment tendrá como parámetro el output del vertex. Hasta aquí simplemente tenemos las funciones creadas con sus correspondientes inputs/ouputs configurados (aunque vacíos). Si vamos a Unity veremos nuestro material rosa y eso es debido a que el shader cree que nuestras funciones son diferentes a las Vertex/Fragment. Tenemos que decirle mediante un #pragma que la función de vertex se llama vert en nuestro código y que la función fragment se llama frag. Puedes ponerle otro nombre a las funciones sin problema, siempre que en esta conexión lo pongas bien: De esta forma ya no tendremos problemas con nuestro shader, salvo por el pequeño problema de que no se ve nada. Inputs y Outputs En este apartado vamos a rellenar nuestros structs de datos con la información que necesitamos en nuestras funciones de vert y frag. Dependiendo del shader que estemos creando vamos a necesitar más o menos datos dentro de los inputs. Por ejemplo si solamente queremos cambiar el color del objeto a rojo, no necesitamos datos de UV. Podemos ver todos los datos que podemos usar en cada función aquí: https://docs.unity3d.com/Manual/SL-VertexProgramInputs.html En nuestro caso vamos a necesitar para las ondulaciones de la bandera, la posición de los vértices y las coordenadas de uv del modelo. Para ello vamos a crear estas dos variables dentro de vertexInput y de vertexOutput. Lo que aparece después de los dos puntos es la semántica y es necesario para conectar los datos. En el artículo anterior de Unity explica esto más detenidamente* * Te darás cuenta de que Unity en el output usa SV_Position, que simplemente es un valor de sistema que lo hace más compatible con los sistemas actuales, para facilitar el entendimiento lo he obviado y he usado el POSITION Llegados a este punto voy a explicar rápidamente los tipos de variables que podemos usar dentro de CG. Como ves he usado fixed2 y fixed4. El número al final hace referencia a vectores de 2 y 4 datos. Sería algo similar a un Vector2 o un Vector4. El tipo fixed es el tipo de menos coste y de menor precisión. Estarás acostumbrado a ver float o int. Estos también pueden ser usados de la misma forma que fixed. Aquí puedes ver los tipos de datos: https://docs.unity3d.com/Manual/SL-DataTypesAndPrecision.html También puedes crear matrices siguiendo la misma lógica, la sintaxis sería “float4x4”,siendo los valores del final las filas y las columnas. Una vez tenemos el vertex con los datos, vamos a pasar al fragment. Este simplemente necesitará un valor, el color final del pixel. En este caso usaremos SV_Target que es el que Unity recomienda por defecto. Como he dicho tienes más información acerca de la semántica en los enlaces anteriores. Como normalmente el fragment solo tiene un valor de devolución, puedes optimizar y borrar el struct de output cambiando el frag de la siguiente manera. El resultado es el mismo que el anterior pero en menos pasos. Ahora vamos a rellenar nuestra función de vertex. Pero antes vamos a necesitar incluir funciones que Unity nos ofrece para facilitarnos el trabajo. Como hemos dicho antes, vamos a convertir la posicion 3D del objeto en posición de pantalla. Para esto vamos a usar una función de Unity llamada UnityObjectToClipPos. Esta función recibe la posición de los vértices y devuelve las posiciones en espacio de pantalla para después usarlas en la función fragment. Para poder usarla vamos a incluir esta línea debajo de los #pragma. El #include sigue la misma lógica que los using en C#, de esta forma podemos hacer uso de funciones que Unity tiene preparadas (como la que hemos comentado antes). Ahora en la función vertex vamos a igualar el output que devolveremos a lo que la función UnityObjectToClipPos nos devuelva. De esta forma convertiremos los vértices para el fragment. También vamos a igualar de momento las uv del input y del output, aunque las usaremos justo ahora. Procedemos ahora a mover por fin los vértices. Para esto vamos a necesitar conocer por un lado la variable interna _Time que posee Unity, similar a Time.deltaTime. Esta es un Vector4 con diferentes tipos de tiempo en cada una. Aquí podemos ver más información de esa y de otras variables internas de Unity: Por otro lado vamos a hacer uso de la función seno de CG para las ondulaciones. Creamos una nueva función en nuestro shader, de nombre flag que devuelva un fixed4. Además tendrá como parámetros la vertexPosition y las uv. Tened en cuenta que el shader compila de arriba hacia abajo, asique si escribís vuestra función al final y la usáis antes, dará error. Siempre tenéis que crear vuestras funciones antes de usarlas (a diferencia de C# por ejemplo). ahora dentro vamos a ir sumando a la vertexPosition el seno de _Time.y (el tiempo por defecto).Lo igualamos en la función vert al o.vertex quedando así: Estamos simplemente moviendo los vértices del input y asignándoles al output. Posteriormente convertimos con el UnityObjectToClipPos y seteamos las uv del input al output. Si probamos el efecto, vemos el movimiento pero no es lo que queremos. Esto es debido a que el seno en Time es constante por lo que siempre se mueve de forma uniforme. Vamos a añadir el valor de uv.x (valor de 0 a 1) y restarle el Time para conseguir el efecto que queremos. De esta forma funciona, pero vamos a necesitar ajustarlo. Para esto vamos a crear tres propiedades de tipo Range. Esto es similar al atributo Range de Unity para los valores numéricos en C#. Te permite mostrar un float en el inspector del material y moverlo con un slider entre dos valores. Ahora podrás ver las tres variables en el editor. Pero para poder usarlas tenemos que declararlas en CG con el mismo nombre que tengan en la propiedad (_Speed,_Frecuency, _Amplitude). Usaremos el tipo fixed. Estas variables las vamos a usar de la siguiente forma: Speed: va a multiplicar al _Time.y para acelerar y reducir la velocidad. Frecuency: va a multiplicar a la resta entre uv.x y la multiplicación del Time y la speed. Justo antes de hacer el seno. Amplitude: multiplica al valor una vez el seno se ha calculado. Estos son los tres cálculos básicos a la hora de modificar la ondulación. Grábalos en tu mente (o apuntalo mejor) porque los usarás muchas más veces en tu vida. Si todo ha ido bien, podrás ajustar los valores como quieras para mejorar la ondulación. Aquí puedes ver mi configuración: Solo nos quedan dos pasos para terminar. El primero es hacer que la bandera se pegue al poste y no ondule. Esto es muy fácil de conseguir teniendo las referencias de uv.x que, como dijimos van de 0 a 1. Solo tenemos que multiplicar el seno que tenemos por la uv.x. De esta forma anclamos la bandera, consiguiendo que la ondulación vaya de mayor a menor fuerza desde el poste (gracias al valor entre 0 y 1 de uv.x) Lo otro que nos queda es añadirle color. Aquí voy a poner dos opciones, la primera es la básica, añadir un color sin más. Si estás cansado y no quieres continuar es la opción que te recomiendo. Podrás volver otro día para ver la segunda opción. En la segunda opción usaré un lerp para darle a la bandera 3 colores diferentes en función de la Y de su UV. Añadir color básico Simplemente tendrás que añadir una propiedad _Color y una variable de CG para conectarla (al igual que la _Speed y los demás valores anteriores). En este caso el color tiene cuatro valores, así que usaremos fixed4. Y en la función frag devolvemos el color a pelo. Añadir color avanzado Si venimos del básico vamos a borrar la propiedad de color (o cambiarle el nombre) y crear otras tres diferentes. Estas se llamarán ColorTop, ColorMiddle, ColorBotton (o el nombre que tu quieras). Estos tres colores serán las tres franjas que tendrá la bandera. Ahora creamos una función nueva encima de frag con el nombre getPixelColor que devolverá un fixed4. Esta función analizará la posición de la uv en Y (la necesita como parámetro) y haciendo uso de la función lerp y step nos devuelve un color u otro. ¿Qué hacen realmente cada una de estas funciones? Puede ser complicado de leer tal y como está, pero solo necesitas saber lo que hace para entenderlo. La función lerp interpola entre dos valores con un valor t. Cuando t es 0 devuelve el primer valor y cuando es 1 devuelve el segundo valor, devolviendo valores intermedios. En nuestro caso no queremos valores intermedios, queremos una interpolación directa dado un valor de referencia. El valor de referencia será ⅓ ya que tenemos 3 franjas. La función step tiene dos parámetros, si el primero es mayor que el segundo, devuelve 1, si es menor devuelve 0. Esto unido al lerp hace que en valores superiores a 0.33 pero inferiores a 0.66 se coloree del color del centro. Y de igual forma en valores superiores e inferiores. Con esto hemos llegado al final de la entrada. Si tienes cualquier duda con esto déjamela en los comentarios. PD: Si queréis que la bandera se muestre en ambas caras, tendréis que cambiar un valor del Cull. Esto es fácil de hacer pero da para otra entrada junto a otros añadidos como el Blend el ZTest o el ZWrite. De momento para que te quede perfecto, solamente tendrás que añadir junto antes del Pass (o dentro del Pass antes de CGPROGRAM) la siguiente linea: Con Cull en Off no ocultará ninguna cara. Nos vemos en la próxima entrada.
  4. Introducción 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. 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. 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. 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). 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: 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. Haremos lo mismo en el canal de Emission para poder ajustar la emisión de algunos objetos posteriormente. 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. 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. 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. 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: Por último vamos a necesitar añadir los ajustes del Stencil debajo de los Tags antes de los diferentes pases. 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: 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. 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. 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. 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) 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: O el dress_material, que no tendría textura: 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: 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. 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á. 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. 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. Con esto ya deberiamos tener visible nuestro modelo únicamente cuando estemos viendolo a través de nuestro quad. 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. 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. 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. 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. 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. 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. 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: 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. 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: 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. 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. Ahora simplemente asegurate de que este objeto está en el Layer PostProcessing 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. 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í: 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. 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: 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. Cualquier duda contacta conmigo via twitter: https://twitter.com/_davidlopez29 o por aquí Hasta pronto!
×
×
  • Create New...