高光效果

V为从顶点指向摄像机的向量,L为从光源指向顶点的向量,R为反射向量


求反射向量R的两种方式 :

1、CG中Reflect函数,可以直接计算出反射向量R

  R = Reflect(I , N); 

  // 参数 :入射光向量I :顶点指向光源的向量,即L的反向量         、   顶点的法向量     注 :都是在世界坐标系中的位置


2、L + R = 2 * cos(N , L) * N  ,当N、L都为单位向量时,cos(N,L) = dot(N,L) 是一个标量值,所以要乘上N,得到向量

      R = 2 * dot(N,L) * N - L


如何证明高亮

    当V与R重合的时候,最为高亮。所以,求得R与V的夹角,即可判断这个顶点是否有高光效果(光滑)



Phong模型

      环境光照(Ambient) + 漫反射光照(Diffuse) + 镜面高光(Specular)


L

   辅助函数WorldSpaceLightDir :参数为顶点在自身坐标系中的位置,函数返回值为 :在世界坐标系中,顶点指向光源位置的向量,所以求入射光线的向量L需要取反


N

   辅助函数UnityObjectToWorldNormal(v.normal),将法向量从自身坐标系变换到世界坐标系中,内部做了向量的规范化。


V

   辅助函数WorldSpaceViewDir(v.vertex) :求从顶点指向摄像机的向量,传入一个自身坐标系中的顶点的位置,返回一个世界坐标系中的从顶点指向摄像机的向量



  

Blinnphong与半角向量 :因为计算反射向量R时,也使用了一次dot操作,运行速度慢,所以可以使用Blinnphong模型和半角向量

      

H

    半角向量,L + V 得出的向量

      float3  H = L + V;

      H = normalize(H);





Shader  "Custom/MySpecular" {


     Properties

     {

          _SpecularColor("_Specular" , Color) = (1,1,1,1)         // 高亮光颜色

          _Shininess("Shininess" , range(1,64)) = 8   // 高亮系数

     }


     SubShader

     {

          Pass

          {

               tags{"LightMode" = "ForwardBase"}


               CGPROGRAM

               #pragma  multi_compile_fwdbase

               #pragma  vertex  vert

               #pragma  fragment  frag

               #include  "unitycg.cginc"

               #include  "lighting.cginc"


               float4  _SpecularColor;

               float  _Shininess;


               struct  v2f {

                      float4  pos : POSITION;

                      fixed4  color : COLOR;

               };


               v2f  vert(appdata_base v)

               {

                      v2f  o;

                      o.pos = mul(UNITY_MATRIX_MVP, v.vertex);


                      float3  L = normalize(WorldSpaceLightDir(v.vertex));   //世界坐标系中,从顶点指向光源的向量

                      float3  N = UnityObjectToWorldNormal(v.normal);     // 把顶点的法向量,从自身坐标系中变换到世界坐标系中

                      float3  V = normalize(WorldSpaceViewDir(v.vertex));   //世界坐标系中,从顶点指向摄像机的向量


                      // 1、Ambient  Color

                      o.color = UNITY_LIGHTMODEL_AMBIENT;


                     // 2、Diffuse  Color

                     float  ndotl = saturate(dot(N,L));

                     o.color += _LightColor0 * ndotl ;               //平行光的颜色


                     // 3、Specular  Color :高光系数的两种求法 :1、dot(R , V)       2、半角向量

                     // 1

                    //// 求R的两种方式 :(1)、Reflect函数 ;   (2)、R = 2 * dot(N,L) * N - L

                    //// (1)、

                   //float3  I  = -WorldSpaceLightDir(v.vertex);            // 入射光向量I,从顶点指向光源

                   //float3  R = reflect(I , N);

                   //// (2)、

                   ////float3  R = 2 * dot(N , L) * N - L;

                   ////R = normalize(R);

                   ////float  specularScale = pow(saturate(dot(R,V)) , _Shininess);



                   // 2多用半角向量,运算速度快

                   float3  H = L + V ;

                   H = normalize(H);

                   float  specularScale = pow(saturate(dot(H , N)) , _Shininess) ; 


                   o.color.rgb  += _SpecularColor * specularScale;


                   return  o ;

               }


               fixed4  frag(v2f  IN) : COLOR

               {

                     return  IN.color ;

               }


               ENDCG

          }

     }

   

}



Phong模型 :要计算反射向量

Blinnphong模型 :要计算半角向量

计算这两个向量,都是为了计算高光




L :

   辅助函数WorldSpaceLightDir :参数为顶点在自身坐标系中的位置,函数返回值为 :在世界坐标系中,顶点指向光源位置的向量,所以求入射光线的向量L需要取反


N :

   辅助函数UnityObjectToWorldNormal(v.normal),将法向量从自身坐标系变换到世界坐标系中,内部做了向量的规范化。


V :

   辅助函数WorldSpaceViewDir(v.vertex) :求从顶点指向摄像机的向量,传入一个自身坐标系中的顶点的位置,返回一个世界坐标系中的从顶点指向摄像机的向量


### 如何在 Unity 中实现高光效果 #### 使用 Blinn-Phong 光照模型实现高光反射 为了实现在 Unity 中的高光效果,可以采用 Blinn-Phong 光照模型。这种光照模型能够有效地模拟物体表面受到光源照射后的反光特性[^3]。 #### 实现原理 Blinn-Phong 模型通过引入半角向量 H 来优化 Phong 反射模型中的镜面反射计算效率。具体来说: - 半角向量 \(H\) 是由视点方向 V 和光线方向 L 计算得出; - 高光项基于法线 N 与半角向量 H 的夹角大小决定; #### Shader 编写实例 下面是一个简单的 HLSL shader 片段代码片段展示如何应用 Blinn-Phong 进行着色: ```hlsl float4 LightingBlinnPhong(SurfaceOutputStandard s, float3 lightDir, float atten) { float3 halfVector = normalize(lightDir + _WorldSpaceViewPos.xyz); // Specular term calculation with Blinn-Phong model float nh = max(dot(s.Normal, halfVector), 0.0); float spec = pow(nh, s.Specular * 128.0); fixed4 c; c.rgb = (s.Albedo * _LightColor0.rgb * dot(s.Normal, lightDir) * atten + _LightColor0.rgb * spec * s.Gloss * atten); c.a = s.Alpha; return c; } ``` 上述代码定义了 `LightingBlinnPhong` 函数用于计算最终颜色输出,其中包含了漫反射和镜面反射两个部分。特别注意的是 specular 组件使用了 pow 函数来增强高光区域的效果。 #### Material 设置 创建一个新的材质并将其设置为自定义着色器后,在 Inspector 窗口中调整 Glossiness 参数可控制高光范围,而 Metallic 则影响金属质感的程度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值