庄懂课L09

Fresnel_SF

无黑盒:法线方向点积视角方向,得到一个中间白四周黑的效果,然后再用One Minus节点取反,用Power节点控制菲尼尔的强度

SF简易版连法:一个SIider控制强度,然后一个Fresnel节点。自己连的时候比较推荐使用这个简易连法

MatCap_SF(动起来有点假)

算法:将nDir从切线空间转到观察空间,取RG通道Remap到(0~1),作为uv对Matcap图采样;

叠加菲涅尔效果模拟金属和非金属不同质感

什么是CubeMap 

简单理解就是全景图,很早期的CubeMap是存在六张贴图中,HDR图也是CubeMap映射后的结果

CubeMap_SF

实现:①SF中有现成CubeMap节点,实现起来并不复杂;注意两个输入节点

          ②第一个为vrDir,即观察方向的反射方向;注意vDir同样为观察反向的反方向;做reflect之前要乘-1

扫描二维码关注公众号,回复: 15235765 查看本文章

          ③Mip为Cubemap的Mipmap等级

          ④由于是环境的反射,根据物体的粗糙程度的不同反射程度也不同,所以用一个slide节点来控制强度

Matcap_Code

定义面板参数

 Properties
    {
        _NormalMap ("法线贴图", 2D) = "bump" {}
        _Matcap ("Matcap",2D) = "gary"{}
        _FresnelPow ("FresnelPow",Range(0,10)) = 1
        _EncSpecInt ("EnvSpecInt",Range(0,10)) = 1
    }

输入结构,需要拿到顶点信息法线信息切线信息UV信息

struct VertexInput {
                float4 vertex : POSITION;  //顶点信息
                float3 normal : NORMAL;     //法线信息
                float4 tangent : TANGENT; //切线信息
                float2 uv0 : TEXCOORD0;     //UV信息
            };

输出结构,需要拿到屏幕顶点位置UV信息世界空间顶点位置世界空间法线方向世界空间切线方向世界空间副切线方向(后面需要构建TBN矩阵)

 struct VertexOutPut{
                float4 pos : SV_POSITION;     //屏幕顶点位置
                float2 uv0 : TEXCOORD0;        //uv信息
                float4 posWS : TEXCOORD1;   //世界空间顶点位置
                float3 nDirWS : TEXCOORD2;       //世界空间法线方向
                float3 tDirWS : TEXCOORD3;       //世界空间切线方向
                float3 bDirWS : TEXCOORD4;      //世界空间负切线方向
            };

顶点shader 下面的代码计算了世界空间中的法线、切线、副切线方向

VertexOutPut vert (VertexInput v)
            {
                VertexOutPut o = (VertexOutPut)0;     //新建一个输出结构
                o.pos = UnityObjectToClipPos(v.vertex);   //屏幕空间下的顶点信息
                o.uv0 = v.uv0;        //传递UV信息   
                o.posWS = mul(unity_ObjectToWorld, v.vertex);  //顶点位置  os>ws
                o.nDirWS = UnityObjectToWorldNormal(v.vertex);  //法线方向  os>ws
                o.tDirWS = normalize( mul( unity_ObjectToWorld, float4( v.tangent.xyz, 0.0 ) ).xyz );   //切线方向os>ws
                o.bDirWS = normalize(cross(o.nDirWS, o.tDirWS) * v.tangent.w);  //根据nDir tDir 求bDir
                return o;   //将输出结构输出
            }

像素Shader

//准备向量:采样法线贴图并解码,然后构建TBN矩阵,再把采样的贴图和TBN矩阵相乘并归一化

再计算视空间的法线方向,世界空间中的视方向

//准备中间变量:点乘世界空间中的视角和法线方向,remap matcap的UV

//光照模型:采样matcap那张图,计算菲涅尔,再将matcap的采样结果和菲涅尔以及环境高光强度相乘,并返回这个值

fixed4 frag (VertexOutPut i) : COLOR{
                //准备向量
                float3 nDirTS = UnpackNormal(tex2D(_NormalMap ,i.uv0)).rgb;//采样法线贴图并解码
                float3x3 TBN = float3x3(i.tDirWS , i.nDirWS , i.bDirWS); //构建TNB矩阵
                float3 nDirWS = normalize(mul(nDirTS,TBN));  //计算nDirWS 计算菲涅尔
                float3 nDirVS = mul(UNITY_MATRIX_V,nDirWS); //计算MatcapUV
                float3 vDirWS = normalize(_WorldSpaceCameraPos.xyz - i.posWS.xyz);//计算菲涅尔

                // 准备中间变量
                float vDotn = dot(vDirWS ,nDirWS);
                float2 matcapUV = nDirVS.rg * 0.5 + 0.5;

                // 光照模型
                float3 matcap = tex2D(_Matcap , matcapUV);
                float fresnel = pow(max(0.00,1.0 - vDotn),_FresnelPow);
                float3 envSpecLighting = matcap * fresnel * _EncSpecInt;

                return float4 (envSpecLighting,1.0);
            }

猜你喜欢

转载自blog.csdn.net/xu1747902112/article/details/130137304