pbr手写改

Shader "URP/PBR"
{
    Properties
    {
        _BaseColor("_BaseColor", Color) = (1,1,1,1)
        _DiffuseTex("Texture", 2D) = "white" {}
        [Normal]_NormalTex("_NormalTex", 2D) = "bump" {}
        _NormalScale("_NormalScale",Range(0,1)) = 1
        _AO("_AO",Range(0,1))=0
 
        _Metallic("_Metallic", Range(0,1)) = 1
        _Smoothness("_Smoothness", Range(0,1)) = 1
        _LightInt("_LightInt", Range(0,1)) = 0.3  
 
        _EmissivInt("_EmissivInt", Float) = 1
        _EmissivColor("_EmissivColor", Color) = (0,0,0,1) 
 
 
    }
        SubShader
    {
        Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline"}
        LOD 100
 
        HLSLINCLUDE
 
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"        //增加光照函数库
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
        #pragma shader_feature _ADDITIONALLIGHTS
        // 接收阴影所需关键字
        #pragma multi_compile _ _MAIN_LIGHT_SHADOWS                    //接受阴影
        #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE            //产生阴影
        #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS                         //额外光源阴影
        #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS      //开启额外其它光源计算
        #pragma multi_compile _ _SHADOWS_SOFT         //软阴影
        //C缓存区
        CBUFFER_START(UnityPerMaterial)
        float4 _DiffuseTex_ST;
        float4 _Diffuse;
        float _NormalScale,_Metallic,_Smoothness;
        float4 _BaseColor;
        half _AO;
        half _LightInt;
        half _EmissivInt;
        half4 _EmissivColor;
        CBUFFER_END
 
        struct appdata
        {
            float4 positionOS : POSITION;                     //输入顶点
            float4 normalOS : NORMAL;                         //输入法线
            float2 texcoord : TEXCOORD0;                      //输入uv信息
            float4 tangentOS : TANGENT;                       //输入切线
        };
 
        struct v2f
        {
            float2 uv : TEXCOORD0;                            //输出uv
            float4 positionCS : SV_POSITION;                  //齐次位置
            float4 normalWS : TEXCOORD1;                        
            float4 tangentWS : TEXCOORD2;
            float4 btangentWS : TEXCOORD3;
            half4 shadowCoord: TEXCOORD4;
        };
 
        TEXTURE2D(_DiffuseTex);                          SAMPLER(sampler_DiffuseTex);
        TEXTURE2D(_NormalTex);                          SAMPLER(sampler_NormalTex);
       
 
        ENDHLSL
 
 
 
 
        Pass
        {
            Tags{ "LightMode" = "UniversalForward" }
 
 
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
 
            // D 的方法
            float Distribution(float roughness, float nh)
            {
                    float lerpSquareRoughness = pow(lerp(0.01,1, roughness),2);                      // 这里限制最小高光点
                    float D = lerpSquareRoughness / (pow((pow(nh,2) * (lerpSquareRoughness - 1) + 1), 2) * PI);
                    return D;
			}
 
            // G_1
            // 直接光照 G项子项
            inline real G_subSection(float X,float roughness)
            {
                float a = (roughness + 1.0) / 2;
                float k = a * a / 8.0;//UE
                float nominator = X;
                float denominator = X * (1.0 - k) + k;
                return nominator / max(denominator, 0.0000001);//防止分母为0
            }
 
            // G 的方法
            float Geometry(float roughness, float nl, float nv)
            {
                //half k = pow(roughness + 1,2)/8.0;          // 直接光的K值
 
                //half k = pow(roughness,2)/2;                      // 间接光的K值
                return G_subSection(nv, roughness) * G_subSection(nl, roughness);
			}
 
            // 间接光 F 的方法
            float3 IndirF_Function(float NdotV, float3 F0, float roughness)
            {
                float Fre = exp2((-5.55473 * NdotV - 6.98316) * NdotV);
                return F0 + Fre * saturate(1 - roughness - F0);
            }
 
 
 
            // 直接光 F的方法
            float3 FresnelEquation(float3 F0,float lh)
            {
                return F0 + (1.0 - F0) * pow(1.0 - lh, 5);
			}
 
 
 
            //间接光高光 反射探针
            real3 IndirectSpeCube(float3 normalWS, float3 viewWS, float roughness, float AO)
            {
                float3 reflectDirWS = reflect(-viewWS, normalWS);                                                  // 计算出反射向量
                roughness = roughness * (1.7 - 0.7 * roughness);                                                   // Unity内部不是线性 调整下拟合曲线求近似
                float MidLevel = roughness * 6;                                                                    // 把粗糙度remap到0-6 7个阶级 然后进行lod采样
                float4 speColor = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectDirWS, MidLevel);//根据不同的等级进行采样
                #if !defined(UNITY_USE_NATIVE_HDR)
                    return DecodeHDREnvironment(speColor, unity_SpecCube0_HDR) * AO;//用DecodeHDREnvironment将颜色从HDR编码下解码。可以看到采样出的rgbm是一个4通道的值,最后一个m存的是一个参数,解码时将前三个通道表示的颜色乘上xM^y,x和y都是由环境贴图定义的系数,存储在unity_SpecCube0_HDR这个结构中。
                #else
                return speColor.xyz*AO;
            #endif
            }
 
            half3 IndirectSpeFactor(half roughness, half smoothness, half3 BRDFspe, half3 F0, half NdotV)
            {
                #ifdef UNITY_COLORSPACE_GAMMA
                half SurReduction = 1 - 0.28 * roughness * roughness;
                #else
                half SurReduction = 1 / (roughness * roughness + 1);
                #endif
                #if defined(SHADER_API_GLES) 
                half Reflectivity = BRDFspe.x;
                #else
                half Reflectivity = max(max(BRDFspe.x, BRDFspe.y), BRDFspe.z);
                #endif
                half GrazingTSection = saturate(Reflectivity + smoothness);
                half fre = Pow4(1 - NdotV);
                return lerp(F0, GrazingTSection, fre) * SurReduction;
            }
 
 
 
            real3 SH_IndirectionDiff(float3 normal)
            {
                real4 SHCoefficients[7];
                SHCoefficients[0] = unity_SHAr;
                SHCoefficients[1] = unity_SHAg;
                SHCoefficients[2] = unity_SHAb;
                SHCoefficients[3] = unity_SHBr;
                SHCoefficients[4] = unity_SHBg;
                SHCoefficients[5] = unity_SHBb;
                SHCoefficients[6] = unity_SHC;
                float3 Color = SampleSH9(SHCoefficients, normal);
                return max(0, Color);
            }
 
            half3 PBRDirectLightResult(Light light, float3 view,float3 normal, float3 albedo, float rough, float metal)
            {
                half4 lightColor = float4(light.color,1);                                 // 获取光照颜色
                float3 viewDir   = normalize(view);
                float3 normalDir = normalize(normal);
                float3 lightDir  = normalize(light.direction);                            // 获取光照颜色
                float3 halfDir   = normalize(viewDir + lightDir);
 
                float nh = max(saturate(dot(normalDir, halfDir)), 0.001);
                float nl = max(saturate(dot(normalDir, lightDir)),0.001);
                float nv = max(saturate(dot(normalDir, viewDir)),0.01);
                float vh = max(saturate(dot(viewDir, halfDir)),0.0001);
                float hl = max(saturate(dot(halfDir, lightDir)), 0.0001);
 
                half3 F0 = lerp(0.04,albedo.rgb,metal);
 
                half D = Distribution(rough, nh);
                half G = Geometry(rough,nl,nv);
                half3 F = FresnelEquation(F0,hl);
 
                half3 ks = F;
                half3 kd = (1- ks) * (1 - metal);                   // 计算kd
 
 
                half3 SpecularResult = (D * G * F) / (nv * nl * 4);
 
                half3 DirectSpeColor = saturate(SpecularResult * lightColor.rgb * nl * PI );
                half3 DirectDiffColor = kd * albedo.rgb * lightColor.rgb * nl;
 
                half3 directLightResult = DirectDiffColor + DirectSpeColor;
                return directLightResult;
            } 
            v2f vert(appdata v)
            {
                v2f o;
                o.uv = TRANSFORM_TEX(v.texcoord, _DiffuseTex);
                VertexPositionInputs  PositionInputs = GetVertexPositionInputs(v.positionOS.xyz);
                o.positionCS = PositionInputs.positionCS;                          //获取齐次空间位置
                half3 positionWS = PositionInputs.positionWS;                          //获取世界空间位置信息
 
                VertexNormalInputs NormalInputs = GetVertexNormalInputs(v.normalOS.xyz,v.tangentOS);
                o.normalWS =half4(NormalInputs.normalWS.xyz,positionWS.x);                                //  获取世界空间下法线信息
                o.tangentWS = half4(NormalInputs.tangentWS,positionWS.y);                              //  获取世界空间下切线信息
                o.btangentWS = half4(NormalInputs.bitangentWS,positionWS.z);                            //  获取世界空间下副切线信息
                o.shadowCoord=TransformWorldToShadowCoord( positionWS);
              
                return o;
            }
 
            half4 frag(v2f i) : SV_Target
            {
                // ============================================= 贴图纹理 =============================================
                half4 albedo = SAMPLE_TEXTURE2D(_DiffuseTex,sampler_DiffuseTex,i.uv) * _BaseColor;
                half4 normal = SAMPLE_TEXTURE2D(_NormalTex,sampler_NormalTex,i.uv);
                half3 emissive=  _EmissivColor.rgb * _EmissivInt*_Smoothness;
 
                half metallic = _Metallic;
                half smoothness = _Smoothness;
                half roughness = pow((1 - smoothness),2);
 
                half ao = _AO;
                // ============================================== 法线计算 ========================================
                float3x3 TBN = {i.tangentWS.xyz, i.btangentWS.xyz, i.normalWS.xyz};            // 矩阵
                TBN = transpose(TBN);
                float3 norTS = UnpackNormalScale(normal, _NormalScale);                        // 使用变量控制法线的强度
                norTS.z = sqrt(1 - saturate(dot(norTS.xy, norTS.xy)));                        // 规范化法线
 
                half3 N = NormalizeNormalPerPixel(mul(TBN, norTS));                           // 顶点法线和法线贴图融合 = 输出世界空间法线信息
 
                // ================================================ 需要的数据  ==========================================
                   
                Light mainLight = GetMainLight(i.shadowCoord);                                             // 获取光照
                half atten = mainLight.shadowAttenuation * mainLight.distanceAttenuation; 
                float4 lightColor = float4(mainLight.color,1);                                 // 获取光照颜色
 
                half3 positionWS=half3(i.normalWS.w,i.tangentWS.w,i.btangentWS.w);
                float3 viewDir   =  SafeNormalize(GetCameraPositionWS() - positionWS); 
                float3 normalDir = normalize(N);
                float3 lightDir  = normalize(mainLight.direction);
                float3 halfDir   = normalize(viewDir + lightDir);
 
                float nh = max(saturate(dot(normalDir, halfDir)), 0.0001);
                float nl = max(saturate(dot(normalDir, lightDir)),0.01);
                float nv = max(saturate(dot(normalDir, viewDir)),0.01);
                float vh = max(saturate(dot(viewDir, lightDir)),0.0001);
                float hl = max(saturate(dot(halfDir, lightDir)), 0.0001);
 
                float3 F0 = lerp(0.04,albedo.rgb,metallic);
 
 
                // ================================================ 直接光高光反射  ==========================================
 
                half D = Distribution(roughness,nh);
                
 
                half G = Geometry(roughness,nl,nv);

 
                half3 F = FresnelEquation(F0,nh);

 
                float3 SpecularResult = (D * G * F) / (nv * nl * 4);
                float3 SpecColor = saturate(SpecularResult * lightColor.xyz * nl*ao);                    // 这里可以AO
              
                // ================================================ 直接光漫反射  ==========================================
 
                float3 ks = F;
                float3 kd = (1- ks) * (1 - metallic);                   // 计算kd
 
                float3 diffColor = kd * albedo.xyz * lightColor.xyz * nl*atten;                                  // 这里增加自发光
 
                // ================================================ 直接光  ==========================================
                float3 directLightResult = diffColor + SpecColor;
             
                // ================================================ 间接光漫反射  ==========================================
                half3 shcolor = SH_IndirectionDiff(N)*ao;                                         // 这里可以AO
                half3 indirect_ks = IndirF_Function(nv,F0,roughness);                          // 计算 ks
                half3 indirect_kd = (1 - indirect_ks) * (1 - metallic);                        // 计算kd
                half3 indirectDiffColor = shcolor * indirect_kd * albedo.xyz;
                //return half4(indirectDiffColor, 1);
                // ================================================ 间接光高光反射  ==========================================
 
                half3 IndirectSpeCubeColor = IndirectSpeCube(N, viewDir, roughness, ao);
                half3 IndirectSpeCubeFactor = IndirectSpeFactor(roughness, smoothness, SpecularResult, F0, nv);
 
                half3 IndirectSpeColor = IndirectSpeCubeColor * IndirectSpeCubeFactor;
 
                 //return half4(IndirectSpeColor.rgb,1);
                // ================================================ 间接光  ==========================================
                half3 IndirectColor = IndirectSpeColor + indirectDiffColor;
 
                // ================================================ 合并光  ==========================================
                half3 finalCol = IndirectColor + directLightResult;
                #ifdef _ADDITIONALLIGHTS
                int pixelLightCount = GetAdditionalLightsCount();
                for(int index = 0; index < pixelLightCount; index++)
                {
 
                    Light light = GetAdditionalLight(index,positionWS);
                    finalCol += PBRDirectLightResult(light,i.viewDirWS,N,albedo.rgb,roughness,metallic) * _LightInt;          // 多光源计算
 
                }
 
                #endif 
                return half4(finalCol.rgb,1);
            }
            ENDHLSL
        }
                Pass
        {
		    Tags{ "LightMode" = "ShadowCaster" }
		    HLSLPROGRAM
		    #pragma vertex vertshadow
		    #pragma fragment fragshadow
 
 
 
		    v2f vertshadow(appdata v)
		    {
		        v2f o=(v2f) 0;
                float3 posWS = TransformObjectToWorld(v.positionOS.xyz);         //世界空间下顶点位置
                float3 norWS = TransformObjectToWorldNormal(v.normalOS.xyz);           //世界空间下顶点位置
                Light MainLight = GetMainLight();                                     //获取灯光
 
                o.positionCS = TransformWorldToHClip(ApplyShadowBias(posWS,norWS,MainLight.direction));             //这里是公共结构体里调用就可以
                #if UNITY_REVERSED_Z
                o.positionCS.z - min(o.positionCS.z,o.positionCS.w * UNITY_NEAR_CLIP_VALUE);
                #else
                o.positionCS.z - max(o.positionCS.z,o.positionCS.w * UNITY_NEAR_CLIP_VALUE);
                #endif
 
		        return o;
		    }
		    float4 fragshadow(v2f i) : SV_Target
		    {
		        half4 color=half4(0,0,0,1);
		        color.xyz = float3(0.0, 0.0, 0.0);
		        return color;
		    }
		    ENDHLSL
		}
    }
}

你可能感兴趣的:(unity,游戏引擎)