Sombreador de unidad - Lambert difuso

Fórmula de reflexión difusa de Lambert :

Difuso (Difuso) =  color de la fuente de luz * máx. (0, cos (ángulo entre la dirección de la luz y la normal))

Principio de fórmula:

 En la imagen de arriba, se puede ver que cuanto mayor sea el valor del coseno formado por la dirección de iluminación L y la fase normal N del objeto, mayor será la luz reflejada. Cuando el ángulo es de 0 grados, la más fuerte es Cos(0) = 1, y cuando es mayor o igual a 90 grados, es 0 Cos( 90) = 0;

Entonces, primero debemos calcular el coseno del ángulo entre el vector normal N y la dirección de la luz incidente L.

Podemos calcular por su producto escalar, la fórmula es la siguiente:

Después de normalizar el vector, |L| y |N| son ambos 1, que se puede simplificar como:

Implementemos lo siguiente:

Difuso por vértice:

Shader "Unlit/001"
{
    Properties
    {
        // 漫反射颜色
        _Diffuse ("_Diffuse",Color) = (1,1,1,1)
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            float4 _Diffuse;
            struct v2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : POSITION;
                float3 color : Color;
            };

            v2f vert (v2v v)
            {
                v2f o;
                // 将对象空间中的点变换到齐次坐标中的摄像机裁剪空间
                o.vertex = UnityObjectToClipPos(v.vertex);
                // 光源方向
                float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
                // 将法向量转到世界坐标法向量
                float3 normal = UnityObjectToWorldNormal(v.normal);
                // 环境光颜色
                float3 ambinet = UNITY_LIGHTMODEL_AMBIENT.xyz;
                // 光源颜色 0 表示第一套光源 ,场景里可以有多个光源
                float3 lightColor = _LightColor0.xyz;
                // 漫反射公式 计算
                float3 diffuse = _Diffuse * lightColor * max(0,dot(lightDir,normal));
                o.color = diffuse + ambinet;
                return o;   
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float4 color = float4(i.color,1);
                return color;
            }
            ENDCG
        }
    }
}

Fuente difusa rebanada por rebanada:

Shader "Unlit/002"
{
    Properties
    {
        // 漫反射颜色
        _Diffuse ("_Diffuse",Color) = (1,1,1,1)
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            float4 _Diffuse;
            struct v2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;                
            };

            v2f vert (v2v v)
            {
                v2f o;
                // 将对象空间中的点变换到齐次坐标中的摄像机裁剪空间
                o.vertex = UnityObjectToClipPos(v.vertex);
                // 将法向量转到世界坐标法向量
                o.normal = UnityObjectToWorldNormal(v.normal);
                return o;   
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // 光源方向
                float3 lightDir = _WorldSpaceLightPos0.xyz;
                // 光源颜色
                float lightColor = _LightColor0.rgb;
                // 漫反射公式 计算
                float3 diffuse = lightColor * lightDir * max(0,dot(lightDir,i.normal));
                float3 ambinet = UNITY_LIGHTMODEL_AMBIENT.rgb;
                float3 color = diffuse + ambinet;
                return float4(color,1);
            }
            ENDCG
        }
    }
}

Veamos los siguientes efectos: Difuso por vértice a la izquierda,
Difuso por fragmento a la derecha No es obvio en mi computadora), puedes ver los vértices obvios. La reflexión difusa del fragmento es relativamente suave. Por el contrario, corte por fragmento tiene un mejor rendimiento que vértice por vértice.

Efecto de luz de fondo:

 Vemos que la luz de fondo es muy oscura y la textura del modelo es completamente invisible. En este caso, el efecto afectará demasiado la experiencia en el juego, por lo que hay un modelo de iluminación medio Lambert. Esta tecnología es la  fórmula  de Valve en el desarrollo del juego "Half Bar" se propuso en "Life", debido a que esta tecnología se modifica sobre la base del modelo de iluminación Lambert original, por lo que se denomina modelo de iluminación semi-Lambert 

Difusa =  color de la fuente de luz * (cos (ángulo entre la dirección de la luz y la normal) * 0,5 + 0,5)

De hecho, es mapear el rango de resultados de [-1,1] a [0,1]. De esta forma, también habrá cambios de luz y oscuridad en la superficie de la luz de fondo, y no será completamente negra.

No publicaré el código general, pero publicaré la parte de la fórmula.

// 漫反射公式 计算
//float3 diffuse = _Diffuse * lightColor * max(0,dot(lightDir,normal));
float3 diffuse = _Diffuse * lightColor * (dot(lightDir,normal) * 0.5 + 0.5);

frente:

atrás:

Supongo que te gusta

Origin blog.csdn.net/weixin_41316824/article/details/131141255
Recomendado
Clasificación