Unity Shader中关于菲涅尔反射

在学习<<Unity Shader 入门精要>>的时候看到关于菲涅尔反射的部分,由于打错代码得到一个意想不到的结果

先PO出代码:

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'

Shader "Unity Shaders Book/Chapter 10/Fresnel"
{
    Properties
    {
        _Color ("Color Tint",Color)=(1,1,1,1)
        _FresnelScale ("Fresnel Scale",Range(0,1))=0.5
_Cubemap("Reflection Cubemap",Cube)="_Skybox" {}
    }
    SubShader
    {
        Tags{"RenderQueue"="Opaque" "Type"="Geometry"}

        pass
        {
            Tags {"LightMode"="ForwardBase"}

            CGPROGRAM
            #pragma multi_compile_fwdbase
#pragma vertex vert
            #pragma fragment frag

#include "Lighting.cginc"
            #include "AutoLight.cginc"

            fixed4 _Color;
            fixed _FresnelScale;
            samplerCUBE _Cubemap;

            struct a2v
            {
float4 vertex:POSITION;
             float3 normal:NORMAL;
            };
            struct v2f
            {
float4 pos:SV_POSITION;
             float3 worldPos:TEXCOORD0;
             fixed3 worldNormal:TEXCOORD1;
             fixed3 worldViewDir:TEXCOORD2;
             fixed3 worldRefl:TEXCOORD3;
             SHADOW_COORDS(4)
            };
            v2f vert(a2v v)
            {
                v2f o;
                o.pos=UnityObjectToClipPos(v.vertex);
                o.worldPos=mul(unity_ObjectToWorld,v.vertex);
                o.worldNormal=UnityObjectToWorldNormal(v.normal);
                o.worldViewDir=UnityWorldSpaceViewDir(o.worldPos);
                o.worldRefl=reflect(-o.worldViewDir,o.worldNormal);
                TRANSFER_SHADOW(o);
                return o;
            }
            fixed4 frag(v2f i):SV_TARGET
            {
                fixed3 worldNormal=normalize(i.worldNormal);
                fixed3 worldViewDir=normalize(i.worldViewDir);
                fixed3 worldLightDir=normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;

                fixed3 reflection=texCUBE(_Cubemap,i.worldRefl).rgb;
fixed3 diffuse=_LightColor0.rgb*_Color.rgb*max(0,dot(worldViewDir,worldNormal));
                fixed3 fresnel=_FresnelScale+(1-_FresnelScale)*pow(1-worldViewDir*worldNormal,5);
                UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);
                fixed3 color=ambient+lerp(diffuse,reflection,saturate(fresnel))*atten;
                return fixed4(color,1.0);
            }
            ENDCG
        }
    }
    fallback "Reflective/VertexLit"
}

这部分代码中在片元着色器中计算菲涅尔公式的时候弄错了

Sclick菲涅尔近似公式应该为:F=F0+(1-F0)(1-dot(v,n))^5,其中F0为一个反射系数,对应代码中为FresnelScale,用于控制菲涅尔反射的强度,v为视觉方向,n为表面法线

可以注意到的是代码中的菲涅尔公式变为F0+(1-F0)(1-v*n)^5

 所以当FresnelScale为0的时候则得到下图结果


而按照正确的菲涅尔反射则应为


阅读更多
上一篇Unity GUI
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭