top of page
Foto del escritorBraulio Madrid

Cómo usar las propiedades de los shaders en el inspector

Actualizado: 23 jul 2020


Introducción.


La semana pasada estaba experimentando un poco con los shaders, además clasificando los shaders que tengo dentro de un proyecto con el fin de hacer experimentos. Encontré el tema del uso de propiedades en materiales, así como los scripts tienen propiedades capaces de dibujar sliders, cabeceras, direcciones de páginas web de ayuda etc, los materiales también tienen algunas propiedades que pueden dibujarse en el inspector, pero me centraré especialmente en dos propiedades que las vi tremendamente útiles como también difíciles de usar en un principio.


Para comenzar el tema ya ha sido tratado en otras páginas en ingles, pero no tratan a fondo estas dos opciones de las que hablo, así que este blog aporta que la información quede en español complementando mejor la información encontrada.


Que es el Dibujador de propiedades.


El #dibujador de propiedades o #propertyDrawer es una clase dentro de unity que le permite al editor poder dibujar en el inspector o una ventana, botones, casillas de verificación, listas, sliders o barras de desplazamiento. Son elemento destinados a facilitar la lectura de las herramientas el artista entienda mejor los datos y pueda usarlos correctamente. unity permite poder hacer tus propiedades personalizadas, así que tiene un artículo al respecto en la ayuda: http://docs.unity3d.com/ScriptReference/MaterialPropertyDrawer.html


Cómo usar las propiedades.


Propiedades cosméticas.

  • [Header(Cualquier texto)]: Muestra un texto como etiqueta, esto se usa generalmente para categorizar conjuntos de variables expuestas en el inspector. [Space]: Hace un espacio por defecto que separa las propiedades. [Space(50)]: Hace un espacio pero a la distancia en píxeles especificada.

Propiedades de ocultamiento

  • [HideInInspector]: Oculta del inspector una variable. No confundir con [PerRendererData] que prácticamente hace lo mismo con las texturas, luego lo explicaré.

  • [ShowIf(texto)]: Supuestamente los que hace es que si hay activado un toggle(texto) con el mismo nombre que contiene la propiedad entonces muestra las propiedades ocultas con la etiqueta del mismo nombre, permitiendo organizar muchísimo mejor las propiedades en el inspector.


Lo probé y aunque no me tira ningún mensaje de error, tampoco hay muestras de haber existido en la documentación de unity o si es una propiedad hecha por algún usuario. Por favor si alguien sabe como se usa o si hay pista alguna que me responda al correo o me escriba algún comentario.


Propiedades de textura

  • [NoScaleOffset]: Elimina los parámetros de Tile Offset en la imagen, ideal si quieres que la textura conserve sus coordenadas UV, como en el caso de hacer un texture atlas.

  • [Normal]: Obliga a usar una textura tipo Normal

  • [PerRendererData]: Oculta propiedades del inspector. El valor de la textura para esta propiedad se consultará desde el MaterialPropertyBlock del renderizador, en lugar del material, esto corresponde al atributo "[PerRendererData]" delante de una propiedad en el código del sombreado.

  • [NonModifiableTextureData]: Evita que se pueda modificar la textura a través del inspector, esto es útil para crear texturas mediante scripts o #render texturas desde una cámara etc. 

Nota: puedes juntar en una textura varias de estas instrucciones.


Propiedades de color

  • [HDR]: Selecciona un color en #HDR

  • [Gamma]: Corrige los valores Float o Range a corrección de color Gamma

  • [Linear]: Corrige los valores Float o Range a corrección de color Linear, Esta característica está por defecto, así que no es necesario llamarla, solo que todo tu proyecto esté en colores Gamma.

Propiedades de rango

Están hechas para usarse con una propiedad Range

  • [PowerSlider(3.0)]: Muestra un Slider solo en propiedades que usan rangos que no es lineal. Esta característica no funciona muy bien, la primera vez que lo usas el cursor si se mueve en un comportamiento exponencial, pero después se comporta como el slider por defecto de siempre.

  • [IntRange]: Muestra un Slider que viaja a través de número enteros, útil para esos shaders que usa iteraciones, como octavas en un ruido perlin, o iteraciones de desenfoque gaussiano.


Propiedades de activación.

Están hechas para usarse en una propiedad Float o Range, el valor indica el número de la opción, en el caso de los #Toggles valor menor a 1 es desactivado y valor mayor a uno es activado. En el caso de los #Enums entre 0 y 1 es la primera opción, entre 1 y 2 es la segunda opción y así sucesivamente.


  • [Toggle] o [MaterialToggle]: Muestra un chulo booleano.  Si mal no recuerdo porque no llegué a probarlo lo suficiente. El nombre de la propiedad debe tener el nombre de la característica que se desea activar.

  • [Toggle(TEXTO)] o [MaterialToggle(TEXTO)]: Muestra un chulo booleano, con el nombre de la característica que va a activarse, es más explícito que el anterior, más adelante explicaré como usarlo.

  • [KeywordEnum(texto1,texto2,texto3,textoN)]: Muestra una lista desplegable de opciones, las opciones contenidas dentro del paréntesis.

  • [Enum(UnityEngine.Rendering.BlendMode)]: Muestra una lista desplegable con opciones ya predeterminadas, hay algunas que puedes usar como:

(UnityEngine.Rendering.BlendMode)

(UnityEngine.Rendering.CullMode)

(UnityEngine.Rendering.CompareFunction)

(UnityEngine.Rendering.ColorWriteMask)


Hay algunas cuantas más pero no son tan útiles y hay otras que no son aplicables, por otro lado son realmente útiles para hacer algunos shaders configurables como el BlendMode en shaders de partículas o el CullMode para invertir las caras normales de un modelo o hacerlos doble cara.


Cómo usar las propiedades de activación.


Para usar estas propiedades lo primero es que debe usarse preferiblemente en un Float, las propiedades viene con el siguiente formato.

[Toggle(Option)]_Propiedad("Nombre a mostrar en el inspector", Float tipo de propiedad) = 0.5 Valor predeterminado.


Ahora por si solo esto lo único que hace es mostrar un bonito chulo de verificación que no hace nada realmente interesante, Para hacerlo interesante hay que agregar algunos comandos de preprocesador que permite crear unas definiciones y hacen que el chulo haga realmente algo.


Lo primero es agregar el preprocesador #pragma multi_compile  o #pragma shader_feature VARIANTE. Dentro de CGPROGRAM


hay una diferencia sustancial entre estos preprocesadores. lo que hace multi_compile es que hace copia del mismo shader, una versión con la variante y otra sin la variante y cuando se compila el juego incluye ambas versiones. 
shader_feature hace las mismas copias de la variantes que solo podrás usar en el editor de unity, cuando se compila el juego descarta todas las copias que no han sido utilizadas.
en conclusión multi_compile sirve en esos casos que quieras ambas versiones y que quieras dentro del juego controlar las variantes. como en el caso de la calidad de los shaders típicos de los menús de calidad gráfica. mientras que shader_feature es el artista que desea derivar de un super shader uno más sencillo.

Ahora lo siguiente sería los preprocesadores.


#if OPCION 
    //trozo de código
#else
    //trozo de código
#endif

Dentro de CGPROGRAM y despues de multi_compile

[KeywordEnum(OpcionA, OpcionB, OpcionC)]_Opciones(“Cualquier” Float) = 1.0 Usar un keyword enum es más complejo al anterior pero es un poco similar, lo primero es entender que el nombre de la propiedad hace referencia a la característica que engloba todas las opciones y dentro del paréntesis del atributo ingresas el nombre de cada opción. 


Luego agregas el preprocesador #pragma shader_feature o #pragma multi_compile seguido de un guion bajo luego el nombre que lo engloba, luego otro guion bajo y luego la opción englobada, a continuación un ejemplo:


CGPROGRAM
#pragma multi_compile _OPCIONES_OPCIONA _OPCIONES_OPCIONB _OPCIONES_OPCIONC

Hasta ahora no pasa nada, porque a continuación sigue definir cada opción, primero se registra la característica que engloba a las opciones y luego se registra cada una de las opciones, como se muestra a continuación:


#ifndef OPCIONES
    #if defined (_OPCIONES_OPCIONA)
        #define OPCIONES _OPCIONES_OPCIONA
    #if defined (_OPCIONES_OPCIONB)
        #define OPCIONES _OPCIONES_OPCIONB
    #else
        #define OPCIONES _OPCIONES_OPCIONC
    #endif
#endif

Ya hemos registrado todas las opciones, ahora usaremos los preprocesadores #if#elif o #else para introducir el código o las modificaciones dentro de estas como se muestra a continuación:


#if OPCIONES == _OPCIONES_OPCIONA
     //Trozo de código;
#elif OPCIONES == _OPCIONES_OPCIONB
     //Más trozo de código;
#else
     //El trozo de código para la opción restante;
#endif

Conclusiones:


Aunque se me hizo un poco largo el blog, sé que este quizás sea uno de los más útiles que pueda resultar junto a como hacer un CGINCLUDE, porque te hará pensar cómo hacerte un shader más completo sin tener que escribir varias veces lo mismo, incluir o desechar características, por ejemplo usar un shader que aplique los mapas normales y en la distancia los desactive.


Pero no todo son ventajas, tiene un inconveniente que debe tener en cuenta, cada vez que se usa el preprocesador de shader_feature o multi_compile se compila tantas copias como opciones, por ejemplo si solo haces 10 toggles cada una con 2 opciones implícitas, esto generaría 10^2 = 100 shaders compilados.


Los #enums generan aún más shaders compilados, así que debe pensar sabiamente como usarlo, usando opciones realmente útiles que tengan impacto.


Por último dejo un ejemplo con el shader de ruido de Brian Sharpe que genera varios tipos de ruido


Esto es todo por ahora, espero que haya sido de mucha utilidad como me lo pareció a mí, no siendo más, nos vemos en otro blog.

32 visualizaciones0 comentarios

Yorumlar


bottom of page