Unity PBR学习(一) 一个简单的BRDF

35 篇文章 4 订阅

环境是Unity2019.4.4 ,抄了一个第一档的BRDF,在此记录一下
先从直射光部分(direct light)开始吧

在这里插入图片描述

公式是

在这里插入图片描述
在我的另外一篇里有

然后就是复制了一下 在这里插入图片描述
里的部分内容
其实就是 一个 diffuse项加specular项,最后我简单的架权平均了下😂不知道对不,看起来差不多。

最后上代码

Shader "Unlit/MyBRDF"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Smoothness("Smoothness",Range(0,1))=0.5
    }
    SubShader
    {
        Tags { "RenderType"="Opaque"}

        Pass
        {
            Tags {"LightMode"="ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fwdbase

            #include "UnityCG.cginc"
            #include "UnityLightingCommon.cginc"

            struct a2v
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal:NORMAL;
                float4 tangent:TANGENT;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                float3 normal:TEXCOORD1;
                float3 tangent:TEXCOORD3;
                float2 uv : TEXCOORD0;
                float3 worldPos:TEXCOORD2;
            };

            #define PI 3.14159265f

            sampler2D _MainTex;
            float4 _MainTex_ST;
            half _Smoothness;

            // Pow5 uses the same amount of instructions as generic pow(), but has 2 advantages:
            // 1) better instruction pipelining
            // 2) no need to worry about NaNs
            inline half Pow5 (half x)
            {
                return x*x * x*x * x;
            }

            inline half2 Pow5 (half2 x)
            {
                return x*x * x*x * x;
            }

            inline half3 Pow5 (half3 x)
            {
                return x*x * x*x * x;
            }

            inline half4 Pow5 (half4 x)
            {
                return x*x * x*x * x;
            }

            // Smoothness is the user facing name
            // it should be perceptualSmoothness but we don't want the user to have to deal with this name
            half SmoothnessToRoughness(half smoothness)
            {
                return (1 - smoothness) * (1 - smoothness);
            }

            float SmoothnessToPerceptualRoughness(float smoothness)
            {
                return (1 - smoothness);
            }

            float PerceptualRoughnessToRoughness(float perceptualRoughness)
            {
                return perceptualRoughness * perceptualRoughness;
            }

            half RoughnessToPerceptualRoughness(half roughness)
            {
                return sqrt(roughness);
            }

            v2f vert (a2v v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.worldPos = mul(unity_ObjectToWorld,v.vertex);
                o.normal = UnityObjectToWorldNormal(v.normal);
                o.tangent = UnityObjectToWorldNormal(v.tangent);
                return o;
            }


            // Note: Disney diffuse must be multiply by diffuseAlbedo / PI. This is done outside of this function.
            half DisneyDiffuse(half NdotV, half NdotL, half LdotH, half perceptualRoughness)
            {
                half fd90 = 0.5 + 2 * LdotH * LdotH * perceptualRoughness;
                // Two schlick fresnel term
                half lightScatter   = (1 + (fd90 - 1) * Pow5(1 - NdotL));
                half viewScatter    = (1 + (fd90 - 1) * Pow5(1 - NdotV));

                return lightScatter * viewScatter;
            }

            // Ref: http://jcgt.org/published/0003/02/03/paper.pdf
            inline float SmithJointGGXVisibilityTerm (float NdotL, float NdotV, float roughness)
            {

                // Approximation of the above formulation (simplify the sqrt, not mathematically correct but close enough)
                float a = roughness;
                float lambdaV = NdotL * (NdotV * (1 - a) + a);
                float lambdaL = NdotV * (NdotL * (1 - a) + a);

                #if defined(SHADER_API_SWITCH)
                    return 0.5f / (lambdaV + lambdaL + 1e-4f); // work-around against hlslcc rounding error
                #else
                    return 0.5f / (lambdaV + lambdaL + 1e-5f);
                #endif
            }

            inline float GGXTerm (float NdotH, float roughness)
            {
                float a2 = roughness * roughness;
                float d = (NdotH * a2 - NdotH) * NdotH + 1.0f; // 2 mad
                return UNITY_INV_PI * a2 / (d * d + 1e-7f); // This function is not intended to be running on Mobile,
                // therefore epsilon is smaller than what can be represented by half
            }

            inline half3 FresnelTerm (half3 F0, half cosA)
            {
                half t = Pow5 (1 - cosA);   // ala Schlick interpoliation
                return F0 + (1-F0) * t;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                float3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos)) ;
                float3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos)) ;
                float3 worldNormal = normalize(i.normal);
                float3 worldTangent = normalize(i.tangent);
                float3 worldHalfDir = normalize(worldViewDir + worldLightDir);

                half NoH = saturate(dot(worldNormal, worldHalfDir));
                half VoH = saturate(dot(worldViewDir, worldHalfDir));
                half NoV = saturate(dot(worldNormal, worldViewDir));
                half NoL = saturate(dot(worldNormal, worldLightDir));
                half LoV = saturate(dot(worldLightDir, worldViewDir));
                half LoH = saturate(dot(worldLightDir, worldHalfDir));

                float perceptualRoughness = SmoothnessToPerceptualRoughness (_Smoothness);
                half3 diffuse = DisneyDiffuse(NoH, NoL, LoH, perceptualRoughness) * NoL;
                float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
                roughness = max(roughness, 0.002);
                float V = SmithJointGGXVisibilityTerm (NoL, NoV, roughness);
                float D = GGXTerm (NoH, roughness);
                float3 F = FresnelTerm (half3(1,1,1), LoH);
                float specularTerm = V * D * PI;
                specularTerm = max(0, specularTerm * NoL);
                // specularTerm *= any(specColor) ? 1.0 : 0.0;

                half3 specular = specularTerm * F;

                col.xyz = diffuse * _LightColor0.rgb + specular * _LightColor0.rgb;
                col.xyz = col.xyz / 2;
                return col;
            }
            ENDCG
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值