UnityShader9.1:光照基础实例

前置:UnityShader9:光照基础回顾

一、漫反射光照

直接上代码:

注意其中 Tags 需要设置光照模式为 ForwardBase,它定义了该 Pass 在光照流水线中的角色,在不同的光照模式下 Unity 的内置光照变量属性和含义都有可能不同

关于光照模式需要了解的的还有不少,不过可以暂时不用这么深究

Shader "Jaihk662/NewSurfaceShader"
{
    Properties
    {
        _DiffuseColor ("DiffuseColor", Color) = (1.0, 1.0, 1.0, 1.0)
    }
    SubShader
    {
        Tags { "LightMode" = "ForwardBase" }
        LOD 200
        PASS 
        {
            CGPROGRAM
            #pragma vertex vert             //声明顶点着色器的函数
            #pragma fragment frag           //声明片段着色器的函数
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
 
            fixed4 _DiffuseColor;
            struct _2vert 
            {
                float4 vertex: POSITION;
                float3 normal: NORMAL;
            };
            struct vert2frag 
            {
                float4 pos: SV_POSITION;
                fixed3 color: COLOR0;
            };
 
            vert2frag vert(_2vert v) 
            {
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                fixed3 wNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject)); 
                fixed3 wLightDir = normalize(_WorldSpaceLightPos0.xyz);
                fixed3 diffuse = _LightColor0.rgb * _DiffuseColor.rgb * saturate(dot(wNormal, wLightDir));

                vert2frag o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.color = ambient + diffuse;
                return o;
            }
            fixed4 frag(vert2frag i): SV_Target 
            {
                return fixed4(i.color, 1.0); 
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

效果如下:

代码中用到的 CG 数学方法:

  • saturate(x):将 x 中的所有参数都截取到 [0, 1] 的范围内

关于 CG 中所有的数学方法百科,可以见下一章

关于 Lighting.cginc:

若代码中用了 ForwardBase 光照模式,并且场景中有且只有一个光源:平行光,此时就可使用下面的光照参数(不同模式下参数含义可能不同,关于前向渲染模式具体可参考:https://blog.csdn.net/Jaihk662/article/details/112055588

扫描二维码关注公众号,回复: 12476338 查看本文章
  • _WorldSpaceLightPos0:光源方向
  • _LightColor0:光源颜色

关于环境光 UNITY_LIGHTMODEL_AMBIENT

在 Window → Rendering → LightingSetting → 下面这个界面设置,Source 选项默认是天空盒

在着色器中,只需要通过 Unity 的内置变量 UNITY_LIGHTMODEL_AMBIENT 就可以得到对应的环境光颜色和强度信息

同理,逐像素光照代码如下:

Shader "Jaihk662/NewSurfaceShader"
{
    Properties
    {
        _DiffuseColor ("DiffuseColor", Color) = (1.0, 1.0, 1.0, 1.0)
    }
    SubShader
    {
        LOD 200
        PASS 
        {
            Tags { "LightMode" = "ForwardBase" }

            CGPROGRAM
            #pragma vertex vert             //声明顶点着色器的函数
            #pragma fragment frag           //声明片段着色器的函数
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
 
            fixed4 _DiffuseColor;
            struct _2vert 
            {
                float4 vertex: POSITION;
                float3 normal: NORMAL;
            };
            struct vert2frag 
            {
                float4 pos: SV_POSITION;
                fixed3 wNormal: NORMAL;
            };
 
            vert2frag vert(_2vert v) 
            {
                vert2frag o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.wNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
                return o;
            }
            fixed4 frag(vert2frag i): SV_Target 
            {
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                fixed3 wNormal = i.wNormal;
                fixed3 wLightDir = normalize(_WorldSpaceLightPos0.xyz);
                fixed3 diffuse = _LightColor0.rgb * _DiffuseColor.rgb * saturate(dot(wNormal, wLightDir));

                return fixed4(ambient + diffuse, 1.0); 
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

二、镜面光照

一样的:

Shader "Jaihk662/NewSurfaceShader"
{
    Properties
    {
        _DiffuseColor ("DiffuseColor", Color) = (1.0, 1.0, 1.0, 1.0)
        _SpecularColor ("SpecularColor", Color) = (1.0, 1.0, 1.0, 1.0)
        _Gloss ("Gloss", Range(8.0, 256)) = 20
    }
    SubShader
    {
        LOD 200
        PASS 
        {
            Tags { "LightMode" = "ForwardBase" }

            CGPROGRAM
            #pragma vertex vert             //声明顶点着色器的函数
            #pragma fragment frag           //声明片段着色器的函数
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
 
            fixed4 _DiffuseColor;
            fixed4 _SpecularColor;
            float _Gloss;
            struct _2vert 
            {
                float4 vertex: POSITION;
                float3 normal: NORMAL;
            };
            struct vert2frag 
            {
                float4 pos: SV_POSITION;
                float3 wPos: TEXCOORD0;
                float3 wNormal: TEXCOORD1;
            };
 
            vert2frag vert(_2vert v) 
            {
                vert2frag o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.wNormal = mul(v.normal, (float3x3)unity_WorldToObject);
                o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                return o;
            }
            fixed4 frag(vert2frag i): SV_Target 
            {
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                fixed3 w1Normal = normalize(i.wNormal);
                fixed3 wLightDir = normalize(_WorldSpaceLightPos0.xyz);
                fixed3 diffuse = _LightColor0.rgb * _DiffuseColor.rgb * saturate(dot(w1Normal, wLightDir));
                
                fixed3 reflectDir = normalize(reflect(-wLightDir, w1Normal));
                fixed3 viewDir = normalize(_WorldSpaceCameraPos - i.wPos);
                fixed3 specular = _LightColor0.rgb * _SpecularColor.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);

                return fixed4(ambient + diffuse + specular, 1.0); 
            } 
            ENDCG
        }
    }
    FallBack "Specular"
}

猜你喜欢

转载自blog.csdn.net/Jaihk662/article/details/110491599