top of page
Foto del escritorBraulio Madrid

Standard Surface Scattering



En esta ocasión les traigo la continuación al Blog aparentemente inútil de la semana pasada, esta vez vamos a mejorar un poco nuestro archivo CustomLighting.cginc agregando algunas funciones para evitar repeticiones.


Haremos otro modelo de iluminación donde le añadiremos al resultado dispersión de luz sobre el material.


Creando el Shader.

Simplemente crearemos una copia del shader de la semana pasada y solo cambiaremos unas pocas líneas.


En las propiedades agregamos:


Properties{
    _ThicknessMap("Thickness map", 2D) = "black" {}
    _Distortion("Normal Distortion", float) = 0
    _SSSConcentration("SSS Area Concentration", float) = 0
    _SSSScale("SSS Scale", float) = 0
    [HDR]_SSSColor("SSS color", Color) = (1,1,1,1)
}

En los #pragma cambiamos:


#pragma surface surf StandardOverride fullforwardshadows
// Lo cambiamos a:
#pragma surface surf SSS fullforwardshadows 

En las variables que recibe de las propiedades agregamos:


sampler2D _MainTex;
sampler2D _Normal;
sampler2D _ThicknessMap

struct Input{
    float2 uv_MainTex;
    float2 uv_Normal;
};

En los parámetros de la función surf cambiamos:

void surf (Input IN, inout SurfaceOutputOverride o)
// Lo cambiamos por:
void surf (Input IN, inout SurfaceOutputSSS o)

Modificando CustomLigthning.cginc


Abriremos el archivo y antes del modelo de iluminación Standard Override agregaremos tres nuevas variables.

float _SSSConcentration;
float _SSSScale;
fixed4 _SSSColor;

Luego agregaremos una nueva función que será el color de la dispersión de luz.

fixed4 SurfaceScatterColor(float3 giColor, float3 giDir, float3 sNormal, float3 vDir, float thick) {
	float3 lightColor = giColor;
	float3 lightDir = giDir + sNormal * _Distortion;
	half sssAmount = pow(saturate(dot(normalize(vDir), -normalize(lightDir))), _SSSConcentration) * _SSSScale * (1.0 - thick);
	return sssAmount * _SSSColor * fixed4(lightColor, 1);
}

Empecemos con la dirección de la luz, tomamos la dirección normal que nos lo da el modelo 3D y lo multiplicamos por el valor de la distorsión, el efecto es el escalado de la dirección ya que estamos multiplicando un flotante por una dirección, estamos aumentando su magnitud. Luego tomamos el resultado y lo sumamos por la dirección de la luz, dando un vector resultante entre la luz y la normal, como en el modelo lambert


Para saber la cantidad de dispersión, primero haremos un producto punto entre la dirección visual y la dirección de la luz que calculamos previamente pero con signo negativo, este signo negativo es es que hace pasar la luz a través del cuerpo del modelo 3d, tomamos todo esto y aplicamos la función saturate que clampea la magnitud del valor entre 0 y 1.


tomamos el resultado y lo elevamos exponencialmente con el valor de _SSSConcentration, esto intensifica el color en algunos puntos mientras que en otros es mas tenue.

Por último se multiplica por la _SSSScale


El retorno final será la multiplicación del vector del monto de dispersión que calculamos, por el color de la translucidez que queremos y el color resultante de la luz.

half4 LightingSSS(SurfaceOutputSSS s, half3 viewDir, UnityGI gi) {
	fixed4 sssColor = SurfaceScatterColor(gi.light.color, gi.light.dir, s.Normal, viewDir, s.Thickness);

	SurfaceOutputStandard r;
	r.Albedo = s.Albedo;
	r.Normal = s.Normal;
	r.Emission = s.Emission;
	r.Metallic = s.Metallic;
	r.Smoothness = s.Smoothness;
	r.Occlusion = s.Occlusion;
	r.Alpha = s.Alpha;
	return LightingStandard(r, viewDir, gi) + sssColor;
}

Por último haremos nuestro iluminación en el cual tomamos el mismo modelo del anterior Blog Standard Override y lo único que haremos es usar la función creada donde le introducimos los parámetros de entrada.


El retorno de nuestro modelo será la suma del modelo Standard y nuestro color resultante de la dispersión.


Por último haremos la función de iluminación global que hay que hacer para el modelo estándar, asegúrese que el nombre de la función sea el mismo, solo agregando en el nombre la palabra "_GI"

inline void LightingSSS_GI(SurfaceOutputSSS s, UnityGIInput data, inout UnityGI gi){	
	UNITY_GI(gi, s, data);
}

Conclusiones.

Este Shader no está totalmente optimizado aun creo que se puede mejorar un poco más, pero tampoco deja mucho margen a la mejora.


Aun hay cosas que desconozco, pero así como hay un modelo Standard, debe ser posible usar un modelo Blinn Phong y un Lambert que tenga incorporado unity


Los modelos de iluminación que se pueden implementar en los modelos Standard, solo le permite añadir colores al resultado final, así que es poco lo que se puede hacer. Si se requiere mayor control es necesario usar Shaders de vértice y fragmento, los shaders de superficie son un shortcut limitado.

17 visualizaciones0 comentarios

Entradas recientes

Ver todo

Commentaires


bottom of page