UnityShader学习记录_高光反射模型

高光反射模型:描述光源照射到模型表面时,该表面在完全镜面反射方向散发的光照。

Phong光照模型:

        Phong光照模型公式:

        cSpecular = (cLight • mSpecular) * Max(0,v • r)^mGloss

        r = l - 2(n • l)n     

        cLight 入射光线颜色和强度。

        mSpecular 材质高光反射颜色

        v 视角方向

         r 光源反射方向

        n 法线

在书写shader代码时,顶点着色器和片元着色器都可以实现光照,顶点着色器写的代码执行效率高,片元着色器片效果会更光滑。

 在shader渲染时 片元的个数往往是顶点的几倍所以 顶点效率高,但却没有片元细致

 逐顶点、逐片元效果图:

 逐顶点代码如下:

//
//简单顶点高光反射
//
Shader "Unlit/HRM01"
{
    Properties
    {
        _Diffuse("Diffuse",Color) = (1,1,1,1)
        //高光反射颜色
        _Specular("Specular",Color) = (1,1,1,1)
        //高光区域
        _Gloss("Gloss",Range(8,255)) = 3
    }
    SubShader
    {
        Tags { "LightMode"="ForwardBase" "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            fixed4 _Diffuse;
            fixed4 _Specular;
            float _Gloss;

            struct v2f
            {
                fixed3 color : Color;
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata_base v)
            {
                v2f o;
                //物体坐标转裁剪空间坐标
                o.vertex = UnityObjectToClipPos(v.vertex);
                //物体法线转世界坐标法线
                float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                //世界坐标光源方向
                fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
                //环境光
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                //漫反射公式
                fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * (dot(worldLight,worldNormal) * 0.5 + 0.5);
                //反射光方向
                fixed3 reflectDir = normalize(reflect(-worldLight,worldNormal));
                //摄像机方向         摄像机世界坐标 - 顶点世界坐标
                fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, v.vertex).xyz);
                //高光公式     
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(reflectDir,viewDir)),_Gloss);
               
                //最终颜色
                o.color = diffuse + ambient + specular;
               // o.color =  specular;
                return o;
            }

            fixed3 frag (v2f i) : SV_Target
            {
                return i.color;
            }
            ENDCG
        }
    }
    Fallback"Specular"
}

逐片元代码如下:

//
//简单高光反射模型
//
Shader "Unlit/HRM02"
{
    Properties
    {
          _Diffuse("Diffuse",Color) = (1,1,1,1)
          _Specular("Specular",Color) = (1,1,1,1)
          _Gloss("Gloss",Range(1,255)) = 3
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            fixed4 _Diffuse;
            fixed4 _Specular;
            float _Gloss;
            
            struct v2f
            {
                float3 worldNormal : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 worldVertex : TEXCOORD1;
            };

            v2f vert (appdata_base v)
            {
                v2f o;
                //物体坐标转裁剪空间坐标
                o.vertex = UnityObjectToClipPos(v.vertex);
               //物体法线转世界坐标法线
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                //物体坐标转世界空间坐标
                o.worldVertex = mul(unity_ObjectToWorld, v.vertex).xyz;
                return o;
            }

            fixed3 frag (v2f i) : SV_Target
            {
                //环境光
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                //世界坐标光源方向
                fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
                //漫反射 点积为负为背光面
                fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * (dot(worldLight,i.worldNormal) * 0.5 + 0.5);
                
                //反射光源方向
                fixed3 reflectDir = normalize(reflect(-worldLight,i.worldNormal));
                //摄像机方向
                //fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldVertex);
                //摄像机方向-unity自带计算世界坐标摄像机方向函数:UnityWorldSpaceViewDir
                fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldVertex));
                //fixed3 viewDir = normalize(WorldSpaceViewDir(i.vertex));

                //高光反射公式
                fixed3 specular = _Specular.rgb * _LightColor0.rgb * pow(saturate(dot(reflectDir,viewDir)),_Gloss);
               
                //最终颜色
                fixed3 color = ambient + diffuse + specular;
                return color;
            }
            ENDCG
        }
   
    }   
}

Blinn-Phong 光照模型:

        Blinn模型没有使用反射方向而是应用了一个新的矢量h ,它通过对视角方向和光照方向相加然后归一化得到。

        h = ( v + l ) / |v + l|

        v 视角方向

        l 光照方向

  Blinn-Phong光照模型公式:

        cSpecular = (cLight • mSpecular) * Max(0,n • h)^mGloss

逐片元效果图

 可以看出Blinn-Phong光照模型的高光反射看起来更大一些、更亮一些。在绝大数情况渲染高光会选择Blinn-Phong(UnityShader入门精要 说的)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值