【Unity Build-In管线的SurfaceShader剖析_PBS光照函数】

news2024/11/27 7:40:27

Unity Build-In管线的SurfaceShader剖析

  • 在Unity Build-In 管线(Universal Render Pipeline)
      • 新建一个Standard Surface Shader
        • 文件里的代码如下:
        • 选中"MyPBR.Shader",在Inspector面板,打开"Show generated code"
        • 跳转到VScode,这里有1677行代码
        • 将其复制到shader文件里。
      • PASS
        • 删除不用的pass后的大致结构
        • FallBack "Diffuse"的作用
      • 包含文件
      • 判断语句
        • 如果/是否定义了(语义)
        • 是否使用lightmaps?
        • ifdef和ifndef的条件语句的经典应用
        • high-precision高精度,half-precision半精度
      • 结构体 Struct v2f_surf
        • UNITY_POSITION(pos); = float4 pos :SV_POSITION;
        • pack0 就是_MainTex的uv
          • 在v2f_surf 里声明三个变量用于组成成切线空间下的旋转矩阵
        • 最后v2f_surf 结构的完整代码:
      • vertex顶点着色器
        • 其中appdata_full
        • 整理后的vertex——vert_surf顶点着色器如下:
      • frag_surf 片段着色器
        • 从return c;往前解析
        • UNITY_OPAQUE_ALPHA(c.a);
        • fixed4 c = LightingStandard (o, worldViewDir, gi);
      • LightingStandard (o, worldViewDir, gi)解析
        • LightingStandard 的第一个参数"o":
          • 不同平台的编译指令区分
          • 宏:UNITY_INITIALIZE_OUTPUT(type,name) 解析
          • 金属工作流下的SurfaceOutputStandard结构
          • 给SurfaceOutputStandard 结构内的参数逐一赋值
        • 最后SurfaceOutputStandard 代码和注释
        • SurfaceOutputStandard 代码的注释补充:
          • o.Normal = worldNormal;
      • UnityGI gi;
        • UnityGI结构体
        • UnityLightingCommon.cginc文件
          • UnityLight light; 直接光照包含信息
          • UnityIndirect indirect; 间接光照包含信息
    • 完整的Shader,保留原始计算和注释的代码如下:
      • 新建一个cginc 文件
    • 完整的cginc代码,代码如下:
  • 最后精简后的Shader
  • 最后精简后的cginc代码

在Unity Build-In 管线(Universal Render Pipeline)

新建一个Standard Surface Shader

在这里插入图片描述

  • 命名为MyPBR
  • 双击打开文件
    在这里插入图片描述
文件里的代码如下:
Shader "Custom/MyPBR"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

选中"MyPBR.Shader",在Inspector面板,打开"Show generated code"

在这里插入图片描述

跳转到VScode,这里有1677行代码

将文件 Ctrl K 再 Ctrl 0,折叠代码。
里面有Unity的部分详细注释。
在这里插入图片描述

将其复制到shader文件里。
  • pass 部分的LightMode 注释
  • ForwardBase pass 主要是支持最亮主平行灯的逐像素光照。
  • ForwardAdd pass 是支持其他等的逐像素光照,这个看项目需求是否需要。
  • Deferred pass 是支持延迟渲染,手机上一般很少用这种渲染pass
  • Meta 光照烘焙
  • 保留ForwardBase pass ,其他的都去除。
    // ---- forward rendering base pass:
    Pass {
      Name "FORWARD"
      Tags { "LightMode" = "ForwardBase" }
      ...
    }
    // ---- forward rendering additive lights pass:
    Pass {
      Name "FORWARD"
      Tags { "LightMode" = "ForwardAdd" }
      ...
    }
    // ---- deferred shading pass:
    Pass {
      Name "DEFERRED"
      Tags { "LightMode" = "Deferred" }
      ...
    }
    // ---- meta information extraction pass:
    Pass {
      Name "Meta"
      Tags { "LightMode" = "Meta" }
      ...
    }

PASS

删除不用的pass后的大致结构

在这里插入图片描述

FallBack "Diffuse"的作用
  • 是保证不同平台的兜底着色,还有就是支持阴影,如果去掉阴影可能会不显示,
  }
  //这个的作用是保证不同平台的兜底着色,还有就是支持阴影,如果去掉阴影可能会不显示,
  FallBack "Diffuse"
}

包含文件

  • 这些包含文件,内部会相互包含串联应用。
    在这里插入图片描述
            // #include "HLSLSupport.cginc"
            // #define UNITY_INSTANCED_LOD_FADE
            // #define UNITY_INSTANCED_SH
            // #define UNITY_INSTANCED_LIGHTMAPSTS
            // #include "UnityShaderVariables.cginc"
            // #include "UnityShaderUtilities.cginc"

判断语句

如果/是否定义了(语义)
  • #if !defined(INSTANCIN1G_ON) 表示如果没有定义GPU实例化,那么执行 #if 到 #endif 里面的计算
  • #if defined(INSTANCING_ON) 表示如果定义了GPU实例化,那么执行 #if 到 #endif 里面的计算
  • -------- variant for: when no other keywords are defined
  • #if !defined(INSTANCING_ON)
    在这里插入图片描述
是否使用lightmaps?
  • #ifndef LIGHTMAP_ON 表示如果没有定义LIGHTMAP_ON
  • #ifdef LIGHTMAP_ON 表示如果定义了LIGHTMAP_ON
    在这里插入图片描述
ifdef和ifndef的条件语句的经典应用
  • 经典应用链接
    在这里插入图片描述
high-precision高精度,half-precision半精度
  • 精度片段着色器寄存器
    在这里插入图片描述

结构体 Struct v2f_surf

UNITY_POSITION(pos); = float4 pos :SV_POSITION;
  • UNITY_POSITION(pos);float4 pos :SV_POSITION; 是一个东西;
pack0 就是_MainTex的uv
float2 pack0 : TEXCOORD0; // _MainTex  ,其中pack0 就是_MainTex的uv

在这里插入图片描述

在v2f_surf 里声明三个变量用于组成成切线空间下的旋转矩阵
						   float3 tSpace0:TEXCOORD3;
						   float3 tSpace1:TEXCOORD4;
						   float3 tSpace2:TEXCOORD5;
最后v2f_surf 结构的完整代码:
                        struct v2f_surf
                        {
                            // UNITY_POSITION(pos); = float4 pos :SV_POSITION;!!!!!!!!!!!!!!!!
                            float4 pos :SV_POSITION;
                            float2 pack0 : TEXCOORD0; // _MainTex  ,其中pack0 就是_MainTex的uv
                            float3 worldNormal : TEXCOORD1;
                            float3 worldPos : TEXCOORD2;
                            #if UNITY_SHOULD_SAMPLE_SH
                                half3 sh : TEXCOORD3; // SH 球谐
                            #endif
                            UNITY_FOG_COORDS(4)
                            UNITY_SHADOW_COORDS(5)
                            float3 tSpace0:TEXCOORD6;
                            float3 tSpace1:TEXCOORD7;
                            float3 tSpace2:TEXCOORD8;
                            // #if SHADER_TARGET >= 30
                            //     float4 lmap : TEXCOORD6;
                            // #endif
                            // UNITY_VERTEX_INPUT_INSTANCE_ID
                            // UNITY_VERTEX_OUTPUT_STEREO
                        };

vertex顶点着色器

      v2f_surf vert_surf (appdata_full v)
      {
        UNITY_SETUP_INSTANCE_ID(v);
        v2f_surf o;
        // UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
        // UNITY_TRANSFER_INSTANCE_ID(v,o);
        // UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
        o.pos = UnityObjectToClipPos(v.vertex);
        o.pack0.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
        float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
        float3 worldNormal = UnityObjectToWorldNormal(v.normal);
        #if defined(LIGHTMAP_ON) && defined(DIRLIGHTMAP_COMBINED)
          fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
          fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w;
          fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
        #endif
        #if defined(LIGHTMAP_ON) && defined(DIRLIGHTMAP_COMBINED) && !defined(UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS)
          o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
          o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
          o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
        #endif
        o.worldPos.xyz = worldPos;
        o.worldNormal = worldNormal;
        #ifdef DYNAMICLIGHTMAP_ON
          o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
        #endif
        #ifdef LIGHTMAP_ON
          o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
        #endif

        // SH/ambient and vertex lights
        #ifndef LIGHTMAP_ON
          #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL
            o.sh = 0;
            // Approximated illumination from non-important point lights
            #ifdef VERTEXLIGHT_ON
              o.sh += Shade4PointLights (
              unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
              unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
              unity_4LightAtten0, worldPos, worldNormal);
            #endif
            o.sh = ShadeSHPerVertex (worldNormal, o.sh);
          #endif
        #endif // !LIGHTMAP_ON

        UNITY_TRANSFER_LIGHTING(o,v.texcoord1.xy); // pass shadow and, possibly, light cookie coordinates to pixel shader
        #ifdef FOG_COMBINED_WITH_TSPACE
          UNITY_TRANSFER_FOG_COMBINED_WITH_TSPACE(o,o.pos); // pass fog coordinates to pixel shader
        #elif defined FOG_COMBINED_WITH_WORLD_POS
          UNITY_TRANSFER_FOG_COMBINED_WITH_WORLD_POS(o,o.pos); // pass fog coordinates to pixel shader
        #else
          UNITY_TRANSFER_FOG(o,o.pos); // pass fog coordinates to pixel shader
        #endif
        return o;
      }
其中appdata_full
                v2f_surf vert_surf (appdata_full v)
                {...
                }
  • 在UnityCG.cginc中有具体的结构体数据:
				struct appdata_base
				{...
				};
				struct appdata_tan
				{...
				};
				struct appdata_full {
				    float4 vertex : POSITION;
				    float4 tangent : TANGENT;
				    float3 normal : NORMAL;
				    float4 texcoord : TEXCOORD0;
				    float4 texcoord1 : TEXCOORD1;
				    float4 texcoord2 : TEXCOORD2;
				    float4 texcoord3 : TEXCOORD3;
				    fixed4 color : COLOR;
				    UNITY_VERTEX_INPUT_INSTANCE_ID
				};

在这里插入图片描述

  • UNITY_SETUP_INSTANCE_ID(v);

仅当您要访问片元着色器中的实例化属性时才需要。
关于实例化的Unity官方介绍
在这里插入图片描述

  • UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
    v2f_surf结构体的初始化。
  • LIGHTMAP_ON——烘焙;DIRLIGHTMAP_COMBINED 方向光源
        UNITY_SETUP_INSTANCE_ID(v);
        v2f_surf o;
        // UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
        // UNITY_TRANSFER_INSTANCE_ID(v,o);
        // UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
整理后的vertex——vert_surf顶点着色器如下:
                v2f_surf vert_surf (appdata_full v)
                {
                    // UNITY_SETUP_INSTANCE_ID(v);
                    v2f_surf o;
                    // UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
                    // UNITY_TRANSFER_INSTANCE_ID(v,o);
                    // UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.pack0.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
                    float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                    float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                    // #if defined(LIGHTMAP_ON) && defined(DIRLIGHTMAP_COMBINED)
                    //     fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
                    //     fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w;
                    //     fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
                    // #endif
                    // #if defined(LIGHTMAP_ON) && defined(DIRLIGHTMAP_COMBINED) && !defined(UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS)
                        o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
                        o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
                        o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
                    // #endif
                    o.worldPos.xyz = worldPos;
                    o.worldNormal = worldNormal;
                    // // 实时GI
                    // #ifdef DYNAMICLIGHTMAP_ON
                    //     o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
                    // #endif
                    // // o.lmap.xy光照贴图的UV采样
                    // #ifdef LIGHTMAP_ON
                    //     o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
                    // #endif

                    // SH/ambient and vertex lights
                    // #ifndef LIGHTMAP_ON
                        #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL
                            o.sh = 0;
                            // Approximated illumination from non-important point lights
                            #ifdef VERTEXLIGHT_ON
                                o.sh += Shade4PointLights (
                                unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
                                unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
                                unity_4LightAtten0, worldPos, worldNormal);
                            #endif
                            o.sh = ShadeSHPerVertex (worldNormal, o.sh);
                        #endif
                    // #endif // !LIGHTMAP_ON
                    // UNITY_TRANSFER_LIGHTING(o,v.texcoord1.xy); // pass shadow and, possibly, light cookie coordinates to pixel shader
                    // #ifdef FOG_COMBINED_WITH_TSPACE
                    //     UNITY_TRANSFER_FOG_COMBINED_WITH_TSPACE(o,o.pos); // pass fog coordinates to pixel shader
                    // #elif defined (FOG_COMBINED_WITH_WORLD_POS)
                    //     UNITY_TRANSFER_FOG_COMBINED_WITH_WORLD_POS(o,o.pos); // pass fog coordinates to pixel shader
                    // #else
                        UNITY_TRANSFER_FOG(o,o.pos); // pass fog coordinates to pixel shader
                    // #endif
                    return o;
                }

frag_surf 片段着色器

                fixed4 frag_surf (v2f_surf IN) : SV_Target
                {
                    UNITY_SETUP_INSTANCE_ID(IN);
                    // prepare and unpack data
                    Input surfIN;
                    #ifdef FOG_COMBINED_WITH_TSPACE
                        UNITY_EXTRACT_FOG_FROM_TSPACE(IN);
                    #elif defined (FOG_COMBINED_WITH_WORLD_POS)
                        UNITY_EXTRACT_FOG_FROM_WORLD_POS(IN);
                    #else
                        UNITY_EXTRACT_FOG(IN);
                    #endif
                    UNITY_INITIALIZE_OUTPUT(Input,surfIN);
                    surfIN.uv_MainTex.x = 1.0;
                    surfIN.uv_MainTex = IN.pack0.xy;
                    float3 worldPos = IN.worldPos.xyz;
                    #ifndef USING_DIRECTIONAL_LIGHT
                        fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
                    #else
                        fixed3 lightDir = _WorldSpaceLightPos0.xyz;
                    #endif
                    float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
                    #ifdef UNITY_COMPILER_HLSL
                        SurfaceOutputStandard o = (SurfaceOutputStandard)0;
                    #else
                        SurfaceOutputStandard o;
                    #endif
                    o.Albedo = 0.0;
                    o.Emission = 0.0;
                    o.Alpha = 0.0;
                    o.Occlusion = 1.0;
                    fixed3 normalWorldVertex = fixed3(0,0,1);
                    o.Normal = IN.worldNormal;
                    normalWorldVertex = IN.worldNormal;

                    // call surface function
                    surf (surfIN, o);

                    // compute lighting & shadowing factor
                    UNITY_LIGHT_ATTENUATION(atten, IN, worldPos)
                    fixed4 c = 0;

                    // Setup lighting environment
                    UnityGI gi;
                    UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
                    gi.indirect.diffuse = 0;
                    gi.indirect.specular = 0;
                    gi.light.color = _LightColor0.rgb;
                    gi.light.dir = lightDir;
                    // Call GI (lightmaps/SH/reflections) lighting function
                    UnityGIInput giInput;
                    UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
                    giInput.light = gi.light;
                    giInput.worldPos = worldPos;
                    giInput.worldViewDir = worldViewDir;
                    giInput.atten = atten;
                    #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
                        giInput.lightmapUV = IN.lmap;
                    #else
                        giInput.lightmapUV = 0.0;
                    #endif
                    #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL
                        giInput.ambient = IN.sh;
                    #else
                        giInput.ambient.rgb = 0.0;
                    #endif
                    giInput.probeHDR[0] = unity_SpecCube0_HDR;
                    giInput.probeHDR[1] = unity_SpecCube1_HDR;
                    #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION)
                        giInput.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
                    #endif
                    #ifdef UNITY_SPECCUBE_BOX_PROJECTION
                        giInput.boxMax[0] = unity_SpecCube0_BoxMax;
                        giInput.probePosition[0] = unity_SpecCube0_ProbePosition;
                        giInput.boxMax[1] = unity_SpecCube1_BoxMax;
                        giInput.boxMin[1] = unity_SpecCube1_BoxMin;
                        giInput.probePosition[1] = unity_SpecCube1_ProbePosition;
                    #endif
                    LightingStandard_GI(o, giInput, gi);

                    // realtime lighting: call lighting function
                    c += LightingStandard (o, worldViewDir, gi);
                    UNITY_APPLY_FOG(_unity_fogCoord, c); // apply fog
                    UNITY_OPAQUE_ALPHA(c.a);
                    return c;
                }

从return c;往前解析
  • return c; 返回c。
UNITY_OPAQUE_ALPHA(c.a);
  • #define UNITY_OPAQUE_ALPHA(outputAlpha) outputAlpha = 1.0
  • Alpha值为1.0
    在这里插入图片描述
    另外一个:
    #if defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)
    在这里插入图片描述
fixed4 c = LightingStandard (o, worldViewDir, gi);
  • fixed4 c = LightingStandard (o, worldViewDir, gi); 其中的LightingStandard 再UnityPBSLighting.cginc文件内
    inline half4 LightingStandard (SurfaceOutputStandard s, half3 viewDir, UnityGI gi)
    {
        s.Normal = normalize(s.Normal);

        half oneMinusReflectivity;
        half3 specColor;
        s.Albedo = DiffuseAndSpecularFromMetallic (s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);

        // shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha)
        // this is necessary to handle transparency in physically correct way - only diffuse component gets affected by alpha
        half outputAlpha;
        s.Albedo = PreMultiplyAlpha (s.Albedo, s.Alpha, oneMinusReflectivity, /*out*/ outputAlpha);

        half4 c = UNITY_BRDF_PBS (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
        c.a = outputAlpha;
        return c;
    }

LightingStandard (o, worldViewDir, gi)解析

LightingStandard 的第一个参数"o":

传入的第一个"o",o是片段着色段的开头部分: SurfaceOutputStandard o;
在这里插入图片描述

不同平台的编译指令区分
                    #ifdef UNITY_COMPILER_HLSL
                        SurfaceOutputStandard o = (SurfaceOutputStandard)0;
                    #else
                        SurfaceOutputStandard o;
                    #endif
宏:UNITY_INITIALIZE_OUTPUT(type,name) 解析
  • UNITY_INITIALIZE_OUTPUT(type,name)用于把所给结构体里的各个变量初始化为0。
  • 在HLSLSupport文件里的定义:
  • 用零值初始化任意结构。
  • 某些后端不支持(例如,基于Cg,尤其是嵌套结构)。
  • hlsl2glsl几乎会支持它,除非有数组的结构——所以也不支持。
  • hlsl2glsl:全称High Level Shader Language to OpenGL Shading Language,简写HLSL to GLSL。
// Initialize arbitrary structure with zero values.
// Not supported on some backends (e.g. Cg-based particularly with nested structs).
// hlsl2glsl would almost support it, except with structs that have arrays -- so treat as not supported there either :(
#if defined(UNITY_COMPILER_HLSL) || defined(SHADER_API_PSSL) || defined(UNITY_COMPILER_HLSLCC)
#define UNITY_INITIALIZE_OUTPUT(type,name) name = (type)0;
#else
#define UNITY_INITIALIZE_OUTPUT(type,name)
#endif
金属工作流下的SurfaceOutputStandard结构

在这里插入图片描述

给SurfaceOutputStandard 结构内的参数逐一赋值
  • 这里的void surf (Input IN, inout SurfaceOutputStandard o)主要作用是给SurfaceOutputStandard 结构内的参数逐一赋值。
                void surf (Input IN, inout SurfaceOutputStandard o)
                {
                    // Albedo comes from a texture tinted by color
                    fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
                    o.Albedo = c.rgb;
                    // Metallic and smoothness come from slider variables
                    o.Metallic = _Metallic;
                    o.Smoothness = _Glossiness;
                    o.Alpha = c.a;
                }
最后SurfaceOutputStandard 代码和注释

在这里插入图片描述

SurfaceOutputStandard 代码的注释补充:
o.Normal = worldNormal;
  • appdata结构中定义NORMAL与TANGENT语义。
                struct appdata
                {
                    float4 vertex : POSITION;
                    float4 tangent : TANGENT;
                    float3 normal : NORMAL;
                    float4 texcoord : TEXCOORD0;
                    float4 texcoord1 : TEXCOORD1;
                    float4 texcoord2 : TEXCOORD2;
                    float4 texcoord3 : TEXCOORD3;
                    fixed4 color : COLOR;
                    UNITY_VERTEX_INPUT_INSTANCE_ID
                };
  • v2f_surf中新增声明
    • float3 tSpace0:TEXCOORD6;
    • float3 tSpace1:TEXCOORD7;
    • float3 tSpace2:TEXCOORD8;
    • float2 normal : TEXCOORD9; // _NormalTex
    • 用于组成切线空间下的矩阵。
                        struct v2f_surf
                        {
                            // UNITY_POSITION(pos); = float4 pos :SV_POSITION;!!!!!!!!!!!!!!!!
                            float4 pos :SV_POSITION;
                            float2 pack0 : TEXCOORD0; // _MainTex  ,其中pack0 就是_MainTex的uv
                            float3 worldNormal : TEXCOORD1;
                            float3 worldPos : TEXCOORD2;
                            #if UNITY_SHOULD_SAMPLE_SH
                                half3 sh : TEXCOORD3; // SH 球谐
                            #endif
                            UNITY_FOG_COORDS(4)
                            UNITY_SHADOW_COORDS(5)
                            float3 tSpace0:TEXCOORD6;
                            float3 tSpace1:TEXCOORD7;
                            float3 tSpace2:TEXCOORD8;
                            float2 normal : TEXCOORD9; // _NormalTex

                            // #if SHADER_TARGET >= 30
                            //     float4 lmap : TEXCOORD6;
                            // #endif
                            // UNITY_VERTEX_INPUT_INSTANCE_ID
                            // UNITY_VERTEX_OUTPUT_STEREO
                        };
  • 在顶点着色器中:
                // vertex shader
                v2f_surf vert_surf (appdata v)
                {
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                    // UNITY_SETUP_INSTANCE_ID(v);
                    v2f_surf o;
                    // UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
                    // UNITY_TRANSFER_INSTANCE_ID(v,o);
                    // UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.pack0 = TRANSFORM_TEX(v.texcoord.xy, _MainTex);
                    o.normal = TRANSFORM_TEX(v.texcoord.zw, _NormalTex);

                    float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                    float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                    // #if defined(LIGHTMAP_ON) && defined(DIRLIGHTMAP_COMBINED)
                        fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
                        fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w;
                        fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
                    // #endif
                    // #if defined(LIGHTMAP_ON) && defined(DIRLIGHTMAP_COMBINED) && !defined(UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS)
                        o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
                        o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
                        o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
                    // #endif
                    o.worldPos.xyz = worldPos;
                    // o.worldNormal = worldNormal;
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                    // // 实时GI
                    // #ifdef DYNAMICLIGHTMAP_ON
                    //     o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
                    // #endif
                    // // o.lmap.xy光照贴图的UV采样
                    // #ifdef LIGHTMAP_ON
                    //     o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
                    // #endif
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                    // SH/ambient and vertex lights
                    // #ifndef LIGHTMAP_ON
                        #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL
                            o.sh = 0;
                            // Approximated illumination from non-important point lights
                            #ifdef VERTEXLIGHT_ON
                                o.sh += Shade4PointLights (
                                unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
                                unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
                                unity_4LightAtten0, worldPos, worldNormal);
                            #endif
                            o.sh = ShadeSHPerVertex (worldNormal, o.sh);
                        #endif
                    // #endif // !LIGHTMAP_ON
                    // UNITY_TRANSFER_LIGHTING(o,v.texcoord1.xy); // pass shadow and, possibly, light cookie coordinates to pixel shader
                    // #ifdef FOG_COMBINED_WITH_TSPACE
                    //     UNITY_TRANSFER_FOG_COMBINED_WITH_TSPACE(o,o.pos); // pass fog coordinates to pixel shader
                    // #elif defined (FOG_COMBINED_WITH_WORLD_POS)
                    //     UNITY_TRANSFER_FOG_COMBINED_WITH_WORLD_POS(o,o.pos); // pass fog coordinates to pixel shader
                    // #else
                        UNITY_TRANSFER_FOG(o,o.pos); // pass fog coordinates to pixel shader
                    // #endif
                    return o;
                }
  • 如是在片段着色器的normal填充
                half3 normalTex = UnpackNormal(tex2D(_NormalTex,IN.normal));
                half3 worldNormal = half3(dot(IN.tSpace0,normalTex),dot(IN.tSpace1,normalTex),dot(IN.tSpace2,normalTex));
                o.Normal = worldNormal;

UnityGI gi;

                    // compute lighting & shadowing factor
                    UNITY_LIGHT_ATTENUATION(atten, IN, worldPos)

                    // Setup lighting environment
                    UnityGI gi;
                    UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
                    gi.indirect.diffuse = 0;
                    gi.indirect.specular = 0;
                    gi.light.color = _LightColor0.rgb;
                    gi.light.dir = lightDir;
                    // Call GI (lightmaps/SH/reflections) lighting function
                    UnityGIInput giInput;
                    UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
                    giInput.light = gi.light;
                    giInput.worldPos = worldPos;
                    giInput.worldViewDir = worldViewDir;
                    giInput.atten = atten;
                    #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
                        giInput.lightmapUV = IN.lmap;
                    #else
                        giInput.lightmapUV = 0.0;
                    #endif
                    #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL
                        giInput.ambient = IN.sh;
                    #else
                        giInput.ambient.rgb = 0.0;
                    #endif
                    giInput.probeHDR[0] = unity_SpecCube0_HDR;
                    giInput.probeHDR[1] = unity_SpecCube1_HDR;
                    #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION)
                        giInput.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
                    #endif
                    #ifdef UNITY_SPECCUBE_BOX_PROJECTION
                        giInput.boxMax[0] = unity_SpecCube0_BoxMax;
                        giInput.probePosition[0] = unity_SpecCube0_ProbePosition;
                        giInput.boxMax[1] = unity_SpecCube1_BoxMax;
                        giInput.boxMin[1] = unity_SpecCube1_BoxMin;
                        giInput.probePosition[1] = unity_SpecCube1_ProbePosition;
                    #endif
                    LightingStandard_GI(o, giInput, gi);
UnityGI结构体

在这里插入图片描述

UnityLightingCommon.cginc文件
fixed4 _LightColor0;
fixed4 _SpecColor;

struct UnityLight
{
    half3 color;
    half3 dir;
    half  ndotl; // Deprecated: Ndotl is now calculated on the fly and is no longer stored. Do not used it.
};

struct UnityIndirect
{
    half3 diffuse;
    half3 specular;
};

struct UnityGI
{
    UnityLight light;
    UnityIndirect indirect;
};

struct UnityGIInput
{
    UnityLight light; // pixel light, sent from the engine

    float3 worldPos;
    half3 worldViewDir;
    half atten;
    half3 ambient;

    // interpolated lightmap UVs are passed as full float precision data to fragment shaders
    // so lightmapUV (which is used as a tmp inside of lightmap fragment shaders) should
    // also be full float precision to avoid data loss before sampling a texture.
    float4 lightmapUV; // .xy = static lightmap UV, .zw = dynamic lightmap UV

    #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION)
    float4 boxMin[2];
    #endif
    #ifdef UNITY_SPECCUBE_BOX_PROJECTION
    float4 boxMax[2];
    float4 probePosition[2];
    #endif
    // HDR cubemap properties, use to decompress HDR texture
    float4 probeHDR[2];
};

UnityLight light; 直接光照包含信息
			struct UnityLight
			{
			    half3 color;
			    half3 dir;
			    half  ndotl; // Deprecated: Ndotl is now calculated on the fly and is no longer stored. Do not used it.
			};
UnityIndirect indirect; 间接光照包含信息
			struct UnityIndirect
			{
			    half3 diffuse;
			    half3 specular;
			};

完整的Shader,保留原始计算和注释的代码如下:

// Upgrade NOTE: replaced 'defined FOG_COMBINED_WITH_WORLD_POS' with 'defined (FOG_COMBINED_WITH_WORLD_POS)'

Shader "Custom/MyPBR"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _NormalTex ("NormalTex", 2D) = "bump" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        
        // ------------------------------------------------------------
        // Surface shader code generated out of a CGPROGRAM block:
// pass 部分的LightMode 注释
//ForwardBase pass 主要是支持最亮主平行灯的逐像素光照
//ForwardAdd pass 是支持其他等的逐像素光照,这个看项目需求是否需要。
// Deferred pass 是支持延迟渲染,手机上一般很少用这种渲染pass
// Meta 光照烘焙

        // ---- forward rendering base pass:
        Pass {
            Name "FORWARD"
            Tags { "LightMode" = "ForwardBase" }

            CGPROGRAM
            // compile directives
            #pragma vertex vert_surf
            #pragma fragment frag_surf
            #pragma target 3.0
            #pragma multi_compile_instancing
            #pragma multi_compile_fog
            #pragma multi_compile_fwdbase
            // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            //这些包含文件,内部会相互包含串联应用,

            // #include "HLSLSupport.cginc"
            // #define UNITY_INSTANCED_LOD_FADE
            // #define UNITY_INSTANCED_SH
            // #define UNITY_INSTANCED_LIGHTMAPSTS
            // #include "UnityShaderVariables.cginc"
            // #include "UnityShaderUtilities.cginc"

            // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

            // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

// 是否定义了(语义)
// #if !defined(INSTANCING_ON) 表示如果没有定义,那么执行 #if 到 #endif 里面的计算
// #if defined(INSTANCING_ON) 表示如果定义了,那么执行 #if 到 #endif 里面的计算
// -------- variant for: <when no other keywords are defined>
// #if !defined(INSTANCING_ON)


                // Surface shader code generated based on:
                // writes to per-pixel normal: no
                // writes to emission: no
                // writes to occlusion: no
                // needs world space reflection vector: no
                // needs world space normal vector: no
                // needs screen space position: no
                // needs world space position: no
                // needs view direction: no
                // needs world space view direction: no
                // needs world space position for lighting: YES
                // needs world space view direction for lighting: YES
                // needs world space view direction for lightmaps: no
                // needs vertex color: no
                // needs VFACE: no
                // needs SV_IsFrontFace: no
                // passes tangent-to-world matrix to pixel shader: no
                // reads from normal: no
                // 1 texcoords actually used
                //   float2 _MainTex
                #include "UnityCG.cginc"
                #include "Lighting.cginc"
                #include "UnityPBSLighting.cginc"
                #include "AutoLight.cginc"

                // #define INTERNAL_DATA
                // #define WorldReflectionVector(data,normal) data.worldRefl
                // #define WorldNormalVector(data,normal) normal

                // // Original surface shader snippet:
                // #line 13 ""
                // #ifdef DUMMY_PREPROCESSOR_TO_WORK_AROUND_HLSL_COMPILER_LINE_HANDLING
                // #endif
                // /* UNITY: Original start of shader */
                // // Physically based Standard lighting model, and enable shadows on all light types
                // //#pragma surface surf Standard fullforwardshadows

                // // Use shader model 3.0 target, to get nicer looking lighting
                // //#pragma target 3.0

                half _Glossiness;
                half _Metallic;
                fixed4 _Color;
                sampler2D _MainTex , _NormalTex;
                float4 _MainTex_ST , _NormalTex_ST;
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//struct Input 结构 传到void surf (Input IN, ...),所以这里也可以注释掉。
                // struct Input
                // {
                //     float2 uv_MainTex;
                // };
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                // // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
                // // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
                // // //#pragma instancing_options assumeuniformscaling
                // UNITY_INSTANCING_BUFFER_START(Props)
                // // put more per-instance properties here
                // UNITY_INSTANCING_BUFFER_END(Props)
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//这里的void surf (Input IN, inout SurfaceOutputStandard o)主要作用是给SurfaceOutputStandard 结构内的参数逐一赋值。
                // void surf (Input IN, inout SurfaceOutputStandard o)
                // {
                //     // Albedo comes from a texture tinted by color
                //     fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
                //     o.Albedo = c.rgb;
                //     // Metallic and smoothness come from slider variables
                //     o.Metallic = _Metallic;
                //     o.Smoothness = _Glossiness;
                //     o.Alpha = c.a;
                // }
                
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// 是否使用lightmaps?
// #ifndef LIGHTMAP_ON 表示如果没有定义LIGHTMAP_ON
// #ifdef LIGHTMAP_ON 表示如果定义了LIGHTMAP_ON
//ifdef和ifndef的条件语句的区别

                // vertex-to-fragment interpolation data
                // no lightmaps:
                // #ifndef LIGHTMAP_ON
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                    // 半精度
                    // half-precision fragment shader registers:
                    // #ifdef UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS
                    //     #define FOG_COMBINED_WITH_WORLD_POS
                    //     struct v2f_surf {
                    //         UNITY_POSITION(pos);
                    //         float2 pack0 : TEXCOORD0; // _MainTex
                    //         float3 worldNormal : TEXCOORD1;
                    //         float4 worldPos : TEXCOORD2;
                    //         #if UNITY_SHOULD_SAMPLE_SH
                    //             half3 sh : TEXCOORD3; // SH
                    //         #endif
                    //         UNITY_LIGHTING_COORDS(4,5)
                    //         #if SHADER_TARGET >= 30
                    //             float4 lmap : TEXCOORD6;
                    //         #endif
                    //         UNITY_VERTEX_INPUT_INSTANCE_ID
                    //         UNITY_VERTEX_OUTPUT_STEREO
                    //     };
                    // #endif
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                    // 高精度
                    // high-precision fragment shader registers:
                    // #ifndef UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS
                        struct v2f_surf
                        {
                            // UNITY_POSITION(pos); = float4 pos :SV_POSITION;!!!!!!!!!!!!!!!!
                            float4 pos :SV_POSITION;
                            float2 pack0 : TEXCOORD0; // _MainTex  ,其中pack0 就是_MainTex的uv
                            float3 worldNormal : TEXCOORD1;
                            float3 worldPos : TEXCOORD2;
                            #if UNITY_SHOULD_SAMPLE_SH
                                half3 sh : TEXCOORD3; // SH 球谐
                            #endif
                            UNITY_FOG_COORDS(4)
                            UNITY_SHADOW_COORDS(5)
                            float3 tSpace0:TEXCOORD6;
                            float3 tSpace1:TEXCOORD7;
                            float3 tSpace2:TEXCOORD8;
                            float2 normal : TEXCOORD9; // _NormalTex

                            // #if SHADER_TARGET >= 30
                            //     float4 lmap : TEXCOORD6;
                            // #endif
                            // UNITY_VERTEX_INPUT_INSTANCE_ID
                            // UNITY_VERTEX_OUTPUT_STEREO
                        };
                    // #endif
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                // #endif
                // // with lightmaps:
                // #ifdef LIGHTMAP_ON
                //     // half-precision fragment shader registers:
                //     #ifdef UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS
                //         #define FOG_COMBINED_WITH_WORLD_POS
                //         struct v2f_surf {
                //             UNITY_POSITION(pos);
                //             float2 pack0 : TEXCOORD0; // _MainTex
                //             float3 worldNormal : TEXCOORD1;
                //             float4 worldPos : TEXCOORD2;
                //             float4 lmap : TEXCOORD3;
                //             UNITY_LIGHTING_COORDS(4,5)
                //             UNITY_VERTEX_INPUT_INSTANCE_ID
                //             UNITY_VERTEX_OUTPUT_STEREO
                //         };
                //     #endif
                //     // high-precision fragment shader registers:
                //     #ifndef UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS
                //         struct v2f_surf {
                //             UNITY_POSITION(pos);
                //             float2 pack0 : TEXCOORD0; // _MainTex
                //             float3 worldNormal : TEXCOORD1;
                //             float3 worldPos : TEXCOORD2;
                //             float4 lmap : TEXCOORD3;
                //             UNITY_FOG_COORDS(4)
                //             UNITY_SHADOW_COORDS(5)
                //             #ifdef DIRLIGHTMAP_COMBINED
                //                 float3 tSpace0 : TEXCOORD6;
                //                 float3 tSpace1 : TEXCOORD7;
                //                 float3 tSpace2 : TEXCOORD8;
                //             #endif
                //             UNITY_VERTEX_INPUT_INSTANCE_ID
                //             UNITY_VERTEX_OUTPUT_STEREO
                //         };
                //     #endif
                // #endif
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                struct appdata
                {
                    float4 vertex : POSITION;
                    float4 tangent : TANGENT;
                    float3 normal : NORMAL;
                    float4 texcoord : TEXCOORD0;
                    float4 texcoord1 : TEXCOORD1;
                    float4 texcoord2 : TEXCOORD2;
                    float4 texcoord3 : TEXCOORD3;
                    fixed4 color : COLOR;
                    UNITY_VERTEX_INPUT_INSTANCE_ID
                };

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                // vertex shader
                v2f_surf vert_surf (appdata v)
                {
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                    // UNITY_SETUP_INSTANCE_ID(v);
                    v2f_surf o;
                    // UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
                    // UNITY_TRANSFER_INSTANCE_ID(v,o);
                    // UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.pack0 = TRANSFORM_TEX(v.texcoord.xy, _MainTex);
                    o.normal = TRANSFORM_TEX(v.texcoord.zw, _NormalTex);

                    float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                    float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                    // #if defined(LIGHTMAP_ON) && defined(DIRLIGHTMAP_COMBINED)
                        fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
                        fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w;
                        fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
                    // #endif
                    // #if defined(LIGHTMAP_ON) && defined(DIRLIGHTMAP_COMBINED) && !defined(UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS)
                        o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
                        o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
                        o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
                    // #endif
                    o.worldPos.xyz = worldPos;
                    // o.worldNormal = worldNormal;
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                    // // 实时GI
                    // #ifdef DYNAMICLIGHTMAP_ON
                    //     o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
                    // #endif
                    // // o.lmap.xy光照贴图的UV采样
                    // #ifdef LIGHTMAP_ON
                    //     o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
                    // #endif
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                    // SH/ambient and vertex lights
                    // #ifndef LIGHTMAP_ON
                        #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL
                            o.sh = 0;
                            // Approximated illumination from non-important point lights
                            #ifdef VERTEXLIGHT_ON
                                o.sh += Shade4PointLights (
                                unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
                                unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
                                unity_4LightAtten0, worldPos, worldNormal);
                            #endif
                            o.sh = ShadeSHPerVertex (worldNormal, o.sh);
                        #endif
                    // #endif // !LIGHTMAP_ON
                    // UNITY_TRANSFER_LIGHTING(o,v.texcoord1.xy); // pass shadow and, possibly, light cookie coordinates to pixel shader
                    // #ifdef FOG_COMBINED_WITH_TSPACE
                    //     UNITY_TRANSFER_FOG_COMBINED_WITH_TSPACE(o,o.pos); // pass fog coordinates to pixel shader
                    // #elif defined (FOG_COMBINED_WITH_WORLD_POS)
                    //     UNITY_TRANSFER_FOG_COMBINED_WITH_WORLD_POS(o,o.pos); // pass fog coordinates to pixel shader
                    // #else
                        UNITY_TRANSFER_FOG(o,o.pos); // pass fog coordinates to pixel shader
                    // #endif
                    return o;
                }
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                // fragment shader
                fixed4 frag_surf (v2f_surf IN) : SV_Target
                {
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------


                    // UNITY_SETUP_INSTANCE_ID(IN);
                    // prepare and unpack data
                    // Input surfIN;
                    UNITY_EXTRACT_FOG(IN);
                    // UNITY_INITIALIZE_OUTPUT(Input,surfIN);
                    // #ifdef FOG_COMBINED_WITH_TSPACE
                    //     UNITY_EXTRACT_FOG_FROM_TSPACE(IN);
                    // #elif defined (FOG_COMBINED_WITH_WORLD_POS)
                    //     UNITY_EXTRACT_FOG_FROM_WORLD_POS(IN);
                    // #else
                    //     UNITY_EXTRACT_FOG(IN);
                    // #endif
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                    // surfIN.uv_MainTex.x = 1.0;
                    // IN.uv_MainTex = IN.pack0.xy;
                    float3 worldPos = IN.worldPos.xyz;


                    // #ifndef USING_DIRECTIONAL_LIGHT
                    //     fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
                    // #else
                    //     fixed3 lightDir = _WorldSpaceLightPos0.xyz;
                    // #endif

                    float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//将SurfaceOutputStandard的数据填充完整。
                    SurfaceOutputStandard o;
                    UNITY_INITIALIZE_OUTPUT(SurfaceOutputStandard,o);
                    // #ifdef UNITY_COMPILER_HLSL
                    //     SurfaceOutputStandard o = (SurfaceOutputStandard)0;
                    // #else
                    //     SurfaceOutputStandard o;
                    // #endif

                    fixed4 mainTex = tex2D (_MainTex, IN.pack0) * _Color;
                    o.Albedo = mainTex.rgb;

                    // Metallic and smoothness come from slider variables
                    // fixed4 metallic = tex2D (_MetallicTex, IN.uv_MainTex);//如果要用金属度贴图或者金属度遮罩,可以采样2D贴图,然后填充。
                    o.Metallic = _Metallic;      // 0=non-metal, 1=metal
                    // 平滑是面向用户的名称,它应该是感知平滑,但用户不应该处理它。
                    // 在代码的任何地方,你都会遇到平滑,这就是感知平滑。
                    o.Smoothness = _Glossiness;
                    o.Alpha = mainTex.a;
                    o.Emission = 0.0;
                    //如果有AO贴图,
                    o.Occlusion = 1.0;
                    // fixed3 normalWorldVertex = fixed3(0,0,1);
                    half3 normalTex = UnpackNormal(tex2D(_NormalTex,IN.normal));
                    half3 worldNormal = half3(dot(IN.tSpace0,normalTex),dot(IN.tSpace1,normalTex),dot(IN.tSpace2,normalTex));
                    o.Normal = worldNormal;
                    // normalWorldVertex = IN.worldNormal;
//检索 void surf (Input IN, inout SurfaceOutputStandard o),这里有注释
                    // // call surface function
                    // surf (surfIN, o);
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                    // compute lighting & shadowing factor
                    UNITY_LIGHT_ATTENUATION(atten, IN, worldPos)

                    // Setup lighting environment
                    UnityGI gi;
                    UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
                    gi.indirect.diffuse = 0;
                    gi.indirect.specular = 0;
                    gi.light.color = _LightColor0.rgb;

                    gi.light.dir = _WorldSpaceLightPos0.xyz;
                    // Call GI (lightmaps/SH/reflections) lighting function
                    UnityGIInput giInput;
                    UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
                    giInput.light = gi.light;
                    giInput.worldPos = worldPos;
                    giInput.worldViewDir = worldViewDir;
                    giInput.atten = atten;
                    #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
                        giInput.lightmapUV = IN.lmap;
                    #else
                        giInput.lightmapUV = 0.0;
                    #endif
                    #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL
                        giInput.ambient = IN.sh;
                    #else
                        giInput.ambient.rgb = 0.0;
                    #endif
                    giInput.probeHDR[0] = unity_SpecCube0_HDR;
                    giInput.probeHDR[1] = unity_SpecCube1_HDR;
                    #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION)
                        giInput.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
                    #endif
                    #ifdef UNITY_SPECCUBE_BOX_PROJECTION
                        giInput.boxMax[0] = unity_SpecCube0_BoxMax;
                        giInput.probePosition[0] = unity_SpecCube0_ProbePosition;
                        giInput.boxMax[1] = unity_SpecCube1_BoxMax;
                        giInput.boxMin[1] = unity_SpecCube1_BoxMin;
                        giInput.probePosition[1] = unity_SpecCube1_ProbePosition;
                    #endif
                    LightingStandard_GI(o, giInput, gi);
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
                    
//PBR的核心计算,基于物理着色,BRDF的相关计算
                    // realtime lighting: call lighting function
                    fixed4 c = LightingStandard (o, worldViewDir, gi);
                    UNITY_APPLY_FOG(_unity_fogCoord, c); // apply fog
                    // Alpha值为1.0
                    UNITY_OPAQUE_ALPHA(c.a);
                    return c;
                }

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            // #endif

            // // -------- variant for: INSTANCING_ON 
            // #if defined(INSTANCING_ON)
            // ...
            // #endif
            // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

            ENDCG

        }

    }
    //这个的作用是保证不同平台的兜底着色,还有就是支持阴影,如果去掉阴影可能会不显示,
    FallBack "Diffuse"
}

新建一个cginc 文件

#ifndef MYPBRCGINC_CGINC
    #define MYPBRCGINC_CGINC

#endif

完整的cginc代码,代码如下:

#ifndef MYPBRCGINC_CGINC
    #define MYPBRCGINC_CGINC
// ----------------------------------------------------------------------------
half3 Unity_GlossyEnvironment_MY (UNITY_ARGS_TEXCUBE(tex), half4 hdr, Unity_GlossyEnvironmentData glossIn)
{
    half perceptualRoughness = glossIn.roughness /* perceptualRoughness */ ;

// TODO: CAUTION: remap from Morten may work only with offline convolution, see impact with runtime convolution!
// For now disabled
#if 0
    float m = PerceptualRoughnessToRoughness(perceptualRoughness); // m is the real roughness parameter
    const float fEps = 1.192092896e-07F;        // smallest such that 1.0+FLT_EPSILON != 1.0  (+1e-4h is NOT good here. is visibly very wrong)
    float n =  (2.0/max(fEps, m*m))-2.0;        // remap to spec power. See eq. 21 in --> https://dl.dropboxusercontent.com/u/55891920/papers/mm_brdf.pdf

    n /= 4;                                     // remap from n_dot_h formulatino to n_dot_r. See section "Pre-convolved Cube Maps vs Path Tracers" --> https://s3.amazonaws.com/docs.knaldtech.com/knald/1.0.0/lys_power_drops.html

    perceptualRoughness = pow( 2/(n+2), 0.25);      // remap back to square root of real roughness (0.25 include both the sqrt root of the conversion and sqrt for going from roughness to perceptualRoughness)
#else
    // MM: came up with a surprisingly close approximation to what the #if 0'ed out code above does.
    perceptualRoughness = perceptualRoughness*(1.7 - 0.7*perceptualRoughness);
#endif
// #endif
// #ifndef UNITY_SPECCUBE_LOD_STEPS
// UNITY_SPECCUBE_LOD_STEPS <6
//mip 是一个非线性函数,perceptualRoughness = perceptualRoughness*(1.7 - 0.7*perceptualRoughness);
// perceptualRoughness = perceptualRoughness*(1.7 - 0.7*perceptualRoughness); 简化 x = x*(1.7 - 0.7*x) 在0-1的范围是一个上拱非线性函数
// #define UNITY_SPECCUBE_LOD_STEPS (6)
// #endif
//    perceptualRoughnessToMipmapLevel = perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS;
    half mip = perceptualRoughnessToMipmapLevel(perceptualRoughness);
    half3 R = glossIn.reflUVW;
    half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(tex, R, mip);//tex2Dlod

    return DecodeHDR(rgbm, hdr);
}

// ----------------------------------------------------------------------------

//
// // ----------------------------------------------------------------------------                                              //
//     // GlossyEnvironment - Function to integrate the specular lighting with default sky or reflection probes                 //
// // ----------------------------------------------------------------------------                                              //
//     struct Unity_GlossyEnvironmentData                                                                                       //
//     {                                                                                                                        //
//         // - Deferred case have one cubemap                                                                                  //
//         // - Forward case can have two blended cubemap (unusual should be deprecated).                                       //
//         // Surface properties use for cubemap integration                                                                    //
//         half    roughness; // CAUTION: This is perceptualRoughness but because of compatibility this name can't be change :( //
//         half3   reflUVW;                                                                                                     //
//     };                                                                                                                       //
//

// 计算Gi的镜面反射
    inline half3 UnityGI_IndirectSpecular_MY(UnityGIInput data, half occlusion, Unity_GlossyEnvironmentData glossIn)
    {
        half3 specular;
//如果开启了BoxProjection
        // #ifdef UNITY_SPECCUBE_BOX_PROJECTION
        //     // we will tweak reflUVW in glossIn directly (as we pass it to Unity_GlossyEnvironment_MY twice for probe0 and probe1), so keep original to pass into BoxProjectedCubemapDirection
        //     half3 originalReflUVW = glossIn.reflUVW;
        //     glossIn.reflUVW = BoxProjectedCubemapDirection (originalReflUVW, data.worldPos, data.probePosition[0], data.boxMin[0], data.boxMax[0]);
        // #endif
//如果勾选了Standard材质面板中的禁用反射功能的情况
        #ifdef _GLOSSYREFLECTIONS_OFF
            specular = unity_IndirectSpecColor.rgb;
        #else
            half3 env0 = Unity_GlossyEnvironment_MY (UNITY_PASS_TEXCUBE(unity_SpecCube0), data.probeHDR[0], glossIn);
            #ifdef UNITY_SPECCUBE_BLENDING
                const float kBlendFactor = 0.99999;
                float blendLerp = data.boxMin[0].w;
                UNITY_BRANCH
                if (blendLerp < kBlendFactor)
                {
                    #ifdef UNITY_SPECCUBE_BOX_PROJECTION
                        glossIn.reflUVW = BoxProjectedCubemapDirection (originalReflUVW, data.worldPos, data.probePosition[1], data.boxMin[1], data.boxMax[1]);
                    #endif

                    half3 env1 = Unity_GlossyEnvironment_MY (UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1,unity_SpecCube0), data.probeHDR[1], glossIn);
                    specular = lerp(env1, env0, blendLerp);
                }
                else
                {
                    specular = env0;
                }
            #else
                specular = env0;
            #endif
        #endif

        return specular * occlusion;
    }
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    // UnityGlobalIllumination_MY 重载函数!!!!!!!!!!!!!!!!!!!!!!!!
    // inline UnityGI UnityGlobalIllumination_MY (UnityGIInput data, half occlusion, half3 normalWorld)
    // {
        //     return UnityGI_Base(data, occlusion, normalWorld);
    // }

    inline UnityGI UnityGlobalIllumination_MY (UnityGIInput data, half occlusion, half3 normalWorld, Unity_GlossyEnvironmentData glossIn)
    {
        //UnityGI_Base只计算Gi的漫反射
        UnityGI o_gi = UnityGI_Base(data, occlusion, normalWorld);
        //UnityGI_IndirectSpecular_MY计算Gi的镜面反射
        o_gi.indirect.specular = UnityGI_IndirectSpecular_MY(data, occlusion, glossIn);
        return o_gi;
    }
    // //
    // // Old UnityGlobalIllumination_MY signatures. Kept only for backward compatibility and will be removed soon
    // //

    // inline UnityGI UnityGlobalIllumination_MY (UnityGIInput data, half occlusion, half smoothness, half3 normalWorld, bool reflections)
    // {
        //     if(reflections)
        //     {
            //         Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup_MY(smoothness, data.worldViewDir, normalWorld, float3(0, 0, 0));
            //         return UnityGlobalIllumination_MY(data, occlusion, normalWorld, g);
        //     }
        //     else
        //     {
            //         return UnityGlobalIllumination_MY(data, occlusion, normalWorld);
        //     }
    // }
    // inline UnityGI UnityGlobalIllumination_MY (UnityGIInput data, half occlusion, half smoothness, half3 normalWorld)
    // {
        //     #if defined(UNITY_PASS_DEFERRED) && UNITY_ENABLE_REFLECTION_BUFFERS
        //         // No need to sample reflection probes during deferred G-buffer pass
        //         bool sampleReflections = false;
        //     #else
        //         bool sampleReflections = true;
        //     #endif
        //     return UnityGlobalIllumination_MY (data, occlusion, smoothness, normalWorld, sampleReflections);
    // }

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
    half SmoothnessToPerceptualRoughness(half smoothness)
    {
        return (1 - smoothness);
    }
//
    Unity_GlossyEnvironmentData UnityGlossyEnvironmentSetup_MY(half Smoothness, half3 worldViewDir, half3 Normal, half3 fresnel0)
    {
        Unity_GlossyEnvironmentData g;
        // g.roughness /* perceptualRoughness */   = (1 - smoothness);
        g.roughness /* perceptualRoughness */   = SmoothnessToPerceptualRoughness(Smoothness);
        //反射球的采样坐标
        g.reflUVW   = reflect(-worldViewDir, Normal);

        return g;
    }
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    //PBR 光照模型 GI
    inline void LightingStandard_GI_MY (SurfaceOutputStandard s,UnityGIInput data,inout UnityGI gi)
    {
        //&& 表示的是两个条件都满足,才会执行下面的计算。否则执行 #else 下面的计算。
        //UNITY_PASS_DEFERRED 是延迟渲染
        // 其中UNITY_ENABLE_REFLECTION_BUFFERS - 使用延迟着色时,以延迟方式渲染反射探测
        #if defined(UNITY_PASS_DEFERRED) && UNITY_ENABLE_REFLECTION_BUFFERS
            //UnityGlobalIllumination_MY
            gi = UnityGlobalIllumination_MY(data, s.Occlusion, s.Normal);
        #else
            Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup_MY(s.Smoothness, data.worldViewDir, s.Normal, lerp(unity_ColorSpaceDielectricSpec.rgb, s.Albedo, s.Metallic));
            // 返回gi
            gi = UnityGlobalIllumination_MY(data, s.Occlusion, s.Normal, g);
        #endif

    }

#endif

最后精简后的Shader

Shader "Custom/MyPBR"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _NormalTex ("NormalTex", 2D) = "bump" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
        Pass {
            Name "FORWARD"
            Tags { "LightMode" = "ForwardBase" }
            CGPROGRAM
            #pragma vertex vert_surf
            #pragma fragment frag_surf
            #pragma target 3.0
            #pragma multi_compile_instancing
            #pragma multi_compile_fog
            #pragma multi_compile_fwdbase
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #include "UnityPBSLighting.cginc"
            #include "AutoLight.cginc"
            #include "MYPBRCGINC.cginc"

            half _Glossiness;
            half _Metallic;
            fixed4 _Color;
            sampler2D _MainTex , _NormalTex;
            float4 _MainTex_ST , _NormalTex_ST;
            struct v2f_surf
            {
                float4 pos :SV_POSITION;
                float2 pack0 : TEXCOORD0;
                float3 worldNormal : TEXCOORD1;
                float3 worldPos : TEXCOORD2;
                #if UNITY_SHOULD_SAMPLE_SH
                    half3 sh : TEXCOORD3;
                #endif
                UNITY_FOG_COORDS(4)
                UNITY_SHADOW_COORDS(5)
                float3 tSpace0:TEXCOORD6;
                float3 tSpace1:TEXCOORD7;
                float3 tSpace2:TEXCOORD8;
                float2 normal : TEXCOORD9;
            };
            struct appdata
            {
                float4 vertex : POSITION;
                float4 tangent : TANGENT;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
                float4 texcoord1 : TEXCOORD1;
                float4 texcoord2 : TEXCOORD2;
                float4 texcoord3 : TEXCOORD3;
                fixed4 color : COLOR;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };
            v2f_surf vert_surf (appdata v)
            {
                v2f_surf o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.pack0 = TRANSFORM_TEX(v.texcoord.xy, _MainTex);
                o.normal = TRANSFORM_TEX(v.texcoord.zw, _NormalTex);
                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
                fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w;
                fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
                o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
                o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
                o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
                o.worldPos.xyz = worldPos;
                #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL
                    o.sh = 0;
                    #ifdef VERTEXLIGHT_ON
                        o.sh += Shade4PointLights (
                        unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
                        unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
                        unity_4LightAtten0, worldPos, worldNormal);
                    #endif
                    o.sh = ShadeSHPerVertex (worldNormal, o.sh);
                #endif
                UNITY_TRANSFER_FOG(o,o.pos);
                return o;
            }
            fixed4 frag_surf (v2f_surf IN) : SV_Target
            {
                UNITY_EXTRACT_FOG(IN);
                float3 worldPos = IN.worldPos.xyz;
                float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
                SurfaceOutputStandard o;
                UNITY_INITIALIZE_OUTPUT(SurfaceOutputStandard,o);
                fixed4 mainTex = tex2D (_MainTex, IN.pack0) * _Color;
                o.Albedo = mainTex.rgb;
                o.Metallic = _Metallic;
                o.Smoothness = _Glossiness;
                o.Alpha = mainTex.a;
                o.Emission = 0.0;
                o.Occlusion = 1.0;
                half3 normalTex = UnpackNormal(tex2D(_NormalTex,IN.normal));
                half3 worldNormal = half3(dot(IN.tSpace0,normalTex),dot(IN.tSpace1,normalTex),dot(IN.tSpace2,normalTex));
                o.Normal = worldNormal;
                UNITY_LIGHT_ATTENUATION(atten, IN, worldPos)
                UnityGI gi;
                UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
                gi.indirect.diffuse = 0;
                gi.indirect.specular = 0;
                gi.light.color = _LightColor0.rgb;

                gi.light.dir = _WorldSpaceLightPos0.xyz;
                UnityGIInput giInput;
                UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
                giInput.light = gi.light;
                giInput.worldPos = worldPos;
                giInput.worldViewDir = worldViewDir;
                giInput.atten = atten;
                giInput.lightmapUV = 0.0;
                #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL
                    giInput.ambient = IN.sh;
                #else
                    giInput.ambient.rgb = 0.0;
                #endif
                giInput.probeHDR[0] = unity_SpecCube0_HDR;
                LightingStandard_GI_MY(o, giInput, gi);
                fixed4 c = LightingStandard (o, worldViewDir, gi);
                UNITY_APPLY_FOG(_unity_fogCoord, c);
                UNITY_OPAQUE_ALPHA(c.a);
                return c;
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

最后精简后的cginc代码

#ifndef MYPBRCGINC_CGINC
    #define MYPBRCGINC_CGINC
    half3 Unity_GlossyEnvironment_MY (UNITY_ARGS_TEXCUBE(tex), half4 hdr, Unity_GlossyEnvironmentData glossIn)
    {
        half perceptualRoughness = glossIn.roughness /* perceptualRoughness */ ;
        #if 0
            float m = PerceptualRoughnessToRoughness(perceptualRoughness); // m is the real roughness parameter
            const float fEps = 1.192092896e-07F;        // smallest such that 1.0+FLT_EPSILON != 1.0  (+1e-4h is NOT good here. is visibly very wrong)
            float n =  (2.0/max(fEps, m*m))-2.0;        // remap to spec power. See eq. 21 in --> https://dl.dropboxusercontent.com/u/55891920/papers/mm_brdf.pdf

            n /= 4;                                     // remap from n_dot_h formulatino to n_dot_r. See section "Pre-convolved Cube Maps vs Path Tracers" --> https://s3.amazonaws.com/docs.knaldtech.com/knald/1.0.0/lys_power_drops.html

            perceptualRoughness = pow( 2/(n+2), 0.25);      // remap back to square root of real roughness (0.25 include both the sqrt root of the conversion and sqrt for going from roughness to perceptualRoughness)
        #else
            perceptualRoughness = perceptualRoughness*(1.7 - 0.7*perceptualRoughness);
        #endif
        half mip = perceptualRoughnessToMipmapLevel(perceptualRoughness);
        half3 R = glossIn.reflUVW;
        half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(tex, R, mip);//tex2Dlod
        return DecodeHDR(rgbm, hdr);
    }
    inline half3 UnityGI_IndirectSpecular_MY(UnityGIInput data, half occlusion, Unity_GlossyEnvironmentData glossIn)
    {
        half3 specular;
        #ifdef _GLOSSYREFLECTIONS_OFF
            specular = unity_IndirectSpecColor.rgb;
        #else
            half3 env0 = Unity_GlossyEnvironment_MY (UNITY_PASS_TEXCUBE(unity_SpecCube0), data.probeHDR[0], glossIn);
            #ifdef UNITY_SPECCUBE_BLENDING
                const float kBlendFactor = 0.99999;
                float blendLerp = data.boxMin[0].w;
                UNITY_BRANCH
                if (blendLerp < kBlendFactor)
                {
                    #ifdef UNITY_SPECCUBE_BOX_PROJECTION
                        glossIn.reflUVW = BoxProjectedCubemapDirection (originalReflUVW, data.worldPos, data.probePosition[1], data.boxMin[1], data.boxMax[1]);
                    #endif

                    half3 env1 = Unity_GlossyEnvironment_MY (UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1,unity_SpecCube0), data.probeHDR[1], glossIn);
                    specular = lerp(env1, env0, blendLerp);
                }
                else
                {
                    specular = env0;
                }
            #else
                specular = env0;
            #endif
        #endif

        return specular * occlusion;
    }
    inline UnityGI UnityGlobalIllumination_MY (UnityGIInput data, half occlusion, half3 normalWorld, Unity_GlossyEnvironmentData glossIn)
    {
        UnityGI o_gi = UnityGI_Base(data, occlusion, normalWorld);
        o_gi.indirect.specular = UnityGI_IndirectSpecular_MY(data, occlusion, glossIn);
        return o_gi;
    }
    half SmoothnessToPerceptualRoughness(half smoothness)
    {
        return (1 - smoothness);
    }
    Unity_GlossyEnvironmentData UnityGlossyEnvironmentSetup_MY(half Smoothness, half3 worldViewDir, half3 Normal, half3 fresnel0)
    {
        Unity_GlossyEnvironmentData g;
        g.roughness = SmoothnessToPerceptualRoughness(Smoothness);
        g.reflUVW   = reflect(-worldViewDir, Normal);
        return g;
    }
    inline void LightingStandard_GI_MY (SurfaceOutputStandard s,UnityGIInput data,inout UnityGI gi)
    {
        #if defined(UNITY_PASS_DEFERRED) && UNITY_ENABLE_REFLECTION_BUFFERS
            gi = UnityGlobalIllumination_MY(data, s.Occlusion, s.Normal);
        #else
            Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup_MY(s.Smoothness, data.worldViewDir, s.Normal, lerp(unity_ColorSpaceDielectricSpec.rgb, s.Albedo, s.Metallic));
            gi = UnityGlobalIllumination_MY(data, s.Occlusion, s.Normal, g);
        #endif
    }
#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1052953.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣刷题-哈希表-求两个数组的交集

349 求两个数组的交集 题意&#xff1a;给定两个数组&#xff0c;编写一个函数来计算它们的交集。注意&#xff1a;输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 提示&#xff1a; 1 < nums1.length, nums2.length < 1000 0 < nums1[i], …

TensorFlow-Federated简介与安装

1、简介 TensorFlow Federated&#xff08;TFF&#xff09;是一个用于机器学习和其他分布式数据计算的开源框架。TFF 的开发旨在促进联邦学习 &#xff08;FL&#xff09;的开放研究和实验。联邦学习是一种机器学习方法&#xff0c;其中一个共享的全局模型在许多参与的客户之间…

集线器与交换机有什么区别?一文带你了解

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 梦想从未散场&#xff0c;传奇永不落幕&#xff0c;博主会持续更新优质网络知识、Python知识、Linux知识以及各种小技巧&#xff0c;愿你我共同在CSDN进步 目录 一、集线器 1. 集线器是什么&#xff1f; 2. …

高并发时代到底是Go还是Java?

作为一名用过Java和Go开发过微服务架构程序的在校学生的角度思考&#xff0c;本文将从以下几个方便来讲述Go和Java的区别。 前言 小明&#xff1a;听说Go在天然情况下支持并发 小红&#xff1a;我不管Java就是最好的语言 小明&#xff1a;不行&#xff0c;我要学以下神秘的Go…

vue3 element-ui-plus Carousel 跑马灯 的使用 及 踩坑记录

vue3 element-ui-plus Carousel 跑马灯 的踩坑记录 Carousel 跑马灯首页跑马灯demo Carousel 跑马灯 首先&#xff0c;打开其官网-跑马灯案例 跑马灯代码&#xff1a; <el-carousel :interval"5000" arrow"always"><el-carousel-item v-for"…

“智慧时代的引领者:探索人工智能的无限可能性“

目录 一.背景 二.应用 2.1金融领域 2.2医疗领域 2.3教育领域 三.发展 四.总结: 一.背景 人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;&#xff0c;是指通过计算机程序模拟人类智能的一种技术。它是计算机科学、工程学、语言学、哲学等多…

Halcon 从基础到精通-01- 基本概念

1 HALCON Architecture 【图一】 HALCON的架构如上&#xff0c;其主要的部分&#xff0c;就是图像处理库。 2 HALCON的基本架构 2.1 Operators HALCON库功能的使用都是通过【operators】操作符来实现的。绝大多数的操作符由多种方法构成&#xff0c;具体可以参考给出的下面…

【开发篇】十、Spring缓存:手机验证码的生成与校验

文章目录 1、缓存2、用HashMap模拟自定义缓存3、SpringBoot提供缓存的使用4、手机验证码案例完善 1、缓存 缓存是一种介于数据永久存储介质与数据应用之间的数据临时存储介质使用缓存可以有效的减少低速数据读取过程的次数&#xff08;例如磁盘IO&#xff09;&#xff0c;提高…

驱动插入中断门示例代码

驱动插入中断描述符示例代码 最近做实验&#xff0c;每次在应用层代码写测试代码的时候都要手动挂一个中断描述符&#xff0c;很不方便所以就想着写个驱动挂一个中断门比较省事 驱动测试效果如下&#xff1a; 下面的代码是个架子&#xff0c;用的时候找个驱动历程传递你要插…

wvp-GB28181-pro windows系统编译安装的坑:录像功能不能正常使用

说明 wvp-GB28181-pro 只是包含了实时视频的接入功能&#xff1b; GitHub - 648540858/wvp-GB28181-pro: WEB VIDEO PLATFORM是一个基于GB28181-2016标准实现的网络视频平台&#xff0c;支持NAT穿透&#xff0c;支持海康、大华、宇视等品牌的IPC、NVR、DVR接入。支持国标级联…

“构建高效的前端表单验证与增删改功能实现“

目录 引言1. 基础增删改功能代码展示后端代码 2. 表单验证基本表单验证自定义验证规则 总结 引言 在现代Web开发中&#xff0c;前端表单验证和增删改功能是不可或缺的核心要素。本文将介绍如何使用ElementUI库来实现高效的前端表单验证和增删改功能。我们将从基础开始&#xf…

LFS在VMware Fusion 中启动时两种报错的解决办法

### 环境&#xff1a; LFS版本&#xff1a;LFS12.0 systemd VMware Fusion版本&#xff1a;Player Version 12.0.0 (16880131) PE版本&#xff1a;alpine-standard-3.18.3-x86_64 ### 部署过程&#xff1a; 1. 在云服务器编译LFS并将LFS目录打包&#xff1b; 2.在本地虚拟…

AI项目十三:PaddleOCR训练自定义数据集

若该文为原创文章&#xff0c;转载请注明原文出处。 续上一篇&#xff0c;PaddleOCR环境搭建好了&#xff0c;并测试通过&#xff0c;接下来训练自己的检测模型和识别模型。 paddleocr检测模型训练 1、准备数据集 在PaddleOCR目录下新建文件夹&#xff1a;train_data, 这个…

ChatGPT终于可以进行网络搜索 内容不再限于2021年9月前

微软和谷歌已经让旗下聊天机器人进行网上搜索&#xff0c;并提供原始材料的链接&#xff0c;以提高信息共享的可信度和范围。但是&#xff0c;ChatGPT迄今为止只接受了有时间限制的训练数据&#xff0c;这些数据仅限于从互联网上收集的2021年9月之前的信息。在周三的一系列推文…

一文读懂梯度下降

PPT版本有多个动图&#xff0c;更容易理解

数据结构--栈的实现

数据结构–栈的实现 1.栈的概念和结构&#xff1a; 栈的概念&#xff1a;栈是一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Las…

【面试经典150 | 数组】除自身以外数组的乘积

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;记录左右乘积空间优化 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到…

给牛奶做直播之二

一、前言 给奶牛做直播之一 主要讲了视频的编解码&#xff0c;我们今天接着往下聊&#xff0c;主要介绍一下视频流的网络应用层协议&#xff0c;先简单讲一下视频文件格式与编码&#xff0c;视频文件格式有很多比如以前的AVI、RMVB、MP4等等无数种&#xff0c;视频文件格式和前…

QCefView 简介

什么是QCefView QCefView 是为 Qt 开发的一个封装集成了CEF(Chromium Embedded Framework)库的Wdiget UI组件。使用QCefView可以充分发挥CEF丰富强大的Web能力&#xff0c;快速开发混合架构的应用程序。它不需要开发者理解CEF的细节&#xff0c;能够在Qt中更容易的使用CEF&…

Flutter开发之Package与Plugin

前言 在flutter中有包和插件两个概念&#xff0c;插件 (plugin) 是 package 的一种&#xff0c;全称是 plugin package&#xff0c;我们简称为 plugin&#xff0c;中文叫插件。包(Package)主要指对flutter相关功能的封装&#xff0c;类似于Android中的插件和iOS中的三方库。而插…