top of page
Foto del escritorBraulio Madrid

Shader para los árboles, 1ra parte propiedades.

El #shader a continuación es de los más complejos de ejecutar, pues trabajar con #transparencias no es tan fácil, mover #vértices en un shader de superficie tampoco lo es y agregar #nieve le da más complejidad, sé que habrá maneras mejores de aplicar todas estas características como quizás ir directamente por un shader de vértices y fragmentos, aunque es la manera correcta aún sigue siendo muy compleja porque hay que crear el modelo de iluminación desde el inicio, calculando mínimo dos pases de luz, otro de sombras y niebla antes de poder hacer cualquier cosa.


Como observará a continuación a parte de tratar el color, trataremos por encima el tema del viento, el tema de las colisiones y la nieve, a parte que trataremos también el tema de la transparencia.


Aviso con antelación que puede que nos lleve mas de un blog para explicar todo lo que pasa dentro de este, pues anteriormente me he dado cuenta de que nunca expliqué el tema de las propiedades en el pasado. Vamos a ello.


Preparación:



  • Cree una escena nueva y pon en ella un plano.

  • Agrega al menos un árbol que tenga los vértices coloreados. Aprovecho para que me compres alguna de las tres colecciones que tengo, todos comparten los mismos materiales y la misma textura, además todos tienen los vértices coloreados pensando precisamente en los shaders que mueven vértices.

  • Luego crea un material y lo agregas a las hojas del árbol.

  • Crea un nuevo shader y adjúntalo al material que previamente has creado.


Propiedades:

Properties
{
[Header(Color)]
_MainTex("Base (RGB)", 2D) = "white" {}
_HealthColor("Health Color", Color) = (1,1,1,1)
_NormalMap("Normal", 2D) = "normal" {}
_Cutoff("Alpha cutoff", Range(0,1)) = 0.0

[Header(Wind)]
_NoiseTex("Noise", 2D) = "whiate" {}
_Scale("Noise Scale", Range(0,2)) = 1.0
_Speed("Effect Speed", float) = 1.0

[Header(Collision)]
_FlexMultiplier("Flex", Range(0,1)) = 0.5		_RangeEffect("RangeEffect", Range(0,2)) = 1.0					

[Header(Snow)]
[ShowIf(IF_SNOW)]_SnowLevel("Snow Level", Float) = 1.0
[MaterialToggle(IF_SNOW)] _IfSnow("if Snow", Float) = 1
}

Note que también estamos usando propiedades de inspector o #Drawers para presentar un poco mejor nuestro shader, usando la posibilidad de activar o desactivar la nieve en caso de no necesitarlo, además de agregar algunos carteles a las propiedades.


SubShader
{
    Blend SrcAlpha OneMinusSrcAlpha
    Tags 
    {
        "Queue" = "AlphaTest"
        "RenderType" = "TreeTransparentCutout"
    }
    Cull Off
 ...

Para empezar hablemos un poco de las mezclas (#Blend). Hemos hablado tiempo atrás, muy al inicio de como funciona un shader por dentro, que es como si tomaran la geometría de nuestra malla y la separaran en pequeñas porciones, exactamente en triángulos y los pasaran por líneas separadas, les aplicaran distintos procesos y saliera al final ya modificado, texturizado y ensamblado, a ese proceso se le llama normalmente tubería o #Pipeline y en esta imagen se puede ver los distintos programas por los que pasa la geometría, al final del camino está las mezclas que le da el acabado final


Blend SrcFactor DstFactor: Configura y habilita la mezcla. El color generado es multiplicado por el SrcFactor. El color que ya está en la pantalla es multiplicado por DstFactor y los dos se agregan juntos.


Realmente no soy un experto en mezclas, pero vale la pena perder una tarde experimentando con ellas para ver los resultados, pero hay algunas mezclas ya probadas que pueden funcionar.

Blend SrcAlpha OneMinusSrcAlpha // Traditional transparency 
Blend One OneMinusSrcAlpha // Premultiplied transparency 
Blend One One // Additive 
Blend OneMinusDstColor One // Soft Additive 
Blend DstColor Zero // Multiplicative 
Blend DstColor SrcColor // 2x Multiplicative

Es bueno tener algunas fórmulas matemáticas para poder alcanzar los mismos resultados con nuestros colores para evitarnos el uso de passes con mezclas. Algún día que tenga las fórmulas haré un blog hablando del tema.



Tags:


Queue: Es el orden de dibujado que se produce en el shader, normalmente la gráfica dibuja los objetos desde el punto más lejano superponiendo poco a poco hacia el objeto más cercano, pero en particular el uso de transparencia es un punto intermedio conflictivo entre que el objeto se dibuja de frente, pero a la vez pelea por diluirse hacia atrás, entonces se producen errores cuando no le das el orden correcto superponiendo la transparencia sobre los objetos del frente o a veces desapareciendo del todo porque se ha dibujado detrás del skybox.


Para usos especiales se pueden usar colas intermedias. Internamente, cada cola está representada por índices enteros.


Background = 1000,
Geometry = 2000,
AlphaTest = 2450,
Transparent = 3000 
Overlay =  4000.


Etiquetas de remplazo shader integradas en los shaders de Unity


Todos los shaders integrados de Unity tienen un conjunto de etiquetas “RenderType” que se pueden utilizar al renderizar con shaders de reemplazo. Los valores de etiqueta son los siguientes:

  • Opaque: la mayoría de shaders (Normal, Self Illuminated, Reflective, shaders de terreno).

  • Transparent: la mayoría de shaders semi-transparentes (Transparent, Particle, Font, terrain additive pass shaders).

  • TransparentCutout: shaders de transparencia enmascarada (Transparent Cutout, dos shaders de pase de vegetación).

  • Background: Shaders Skybox.

  • Overlay: Halo, Flare shaders.

  • TreeOpaque: Corteza del árbol del motor de terreno.

  • TreeTransparentCutout: hojas de los árboles del motor de terreno.

  • TreeBillboard: Árboles de cartelera del motor de terreno, estos solo representan un dibujo siempre mirando frente a la cámara.

  • Grass: motor de terreno de la hierba, Nuestro shader se parece concretamente a este tipo.

  • GrassBillboard: pasto de cartelera del motor de terreno, muy similar al anterior, donde una imagen siempre mira hacia la cámara, con la única diferencia que esta siempre se mece por el viento.


Cull o sacrificio:


Hago uso del Cull off, para evitar que las caras internas de la geometría sean renderizados también, Cull Front para ver sacrificar las caras delanteras y cull Back para sacrificar las caras traseras, esta última es la opción por defecto.



Variables, structs y preprocesadores:


A continuación viene las líneas de crear las variables que se pasan a través de los parámetros del material.


Es importante destacar la línea #include "CustomLighting.cginc" y #pragma surf Translucency, pues estas líneas son de cosecha propia de los blogs que hablaban de modelos de iluminación, en dicho capitulo se trató el tema de varios modelos de iluminación, hasta que se logró hacer varios modelos muy útiles, entre ellos la #translucencia, que es permitir que parte de la luz pase a través del material.


Por otra parte he incluido un programa de vértices, porque es necesario mover las hojas de los árboles, normalmente los shaders de superficie no vienen con un programa de vertices y es hasta un poco antinatural porque sobrescribe el que maneja internamente el motor, como había dicho en la introducción, lo ideal seria hacer directamente un shader vertex fragment para esto.



CGPROGRAM
#include "CustomLighting.cginc"
#pragma surface surf Translucency vertex:vert addshadow 
alphatest:_Cutoff 
#pragma target 3.0
#pragma shader_feature IF_SNOW
#include "UnityCG.cginc"

sampler2D _MainTex, _NormalMap, _NoiseTex;
float4 _GLOBALposition;
float _FlexMultiplier, _RangeEffect;
float _Speed;

fixed4 _HealthColor

#if IF_SNOW
    float _SnowLevel;
#endif

struct Input
{
    float2 uv_MainTex;
    float4 color : COLOR;
    float3 worldPos;
};
...

add shadow sirve para que el objeto proyecte sombras y #alphatest para darle transparencia a las hojas a través de la variable _Cutoff, si falta alguno de los dos, el efecto no ocurrirá. Note que el parametro _Cutoff es declarado en los parámetros, pero nunca en las variables, este pasa directamente a una sintaxis muy rara a través de la macro alphatest.


El resto ya es prácticamente igual que en el blog anterior, donde agregamos las funciones para la nieve, el struct también es muy similar al del blog anterior, donde hago uso de la matriz de posición mundial para calcular la altura a la que aparecerá el efecto de la nieve.


 

Por ahora no habrá ninguna conclusión porque el shader no ha terminado, los espero para el próximo blog donde espero que concluya este shader maravilloso, en el siguiente trataré el tema del movimiento de vértices, las falsas colisiones y el efecto de nieve.


No siendo más nos vemos en un próximo blog. Hasta otra.

23 visualizaciones0 comentarios

Comments


bottom of page