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

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 200CGPROGRAM// 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.0sampler2D _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 assumeuniformscalingUNITY_INSTANCING_BUFFER_START(Props)// put more per-instance properties hereUNITY_INSTANCING_BUFFER_END(Props)void surf (Input IN, inout SurfaceOutputStandard o){// Albedo comes from a texture tinted by colorfixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;o.Albedo = c.rgb;// Metallic and smoothness come from slider variableso.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的uvfloat3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;#if UNITY_SHOULD_SAMPLE_SHhalf3 sh : TEXCOORD3; // SH 球谐#endifUNITY_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);#endifo.worldPos.xyz = worldPos;o.worldNormal = worldNormal;#ifdef DYNAMICLIGHTMAP_ONo.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;#endif#ifdef LIGHTMAP_ONo.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_PIXELo.sh = 0;// Approximated illumination from non-important point lights#ifdef VERTEXLIGHT_ONo.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);#endifo.sh = ShadeSHPerVertex (worldNormal, o.sh);#endif#endif // !LIGHTMAP_ONUNITY_TRANSFER_LIGHTING(o,v.texcoord1.xy); // pass shadow and, possibly, light cookie coordinates to pixel shader#ifdef FOG_COMBINED_WITH_TSPACEUNITY_TRANSFER_FOG_COMBINED_WITH_TSPACE(o,o.pos); // pass fog coordinates to pixel shader#elif defined FOG_COMBINED_WITH_WORLD_POSUNITY_TRANSFER_FOG_COMBINED_WITH_WORLD_POS(o,o.pos); // pass fog coordinates to pixel shader#elseUNITY_TRANSFER_FOG(o,o.pos); // pass fog coordinates to pixel shader#endifreturn 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);// #endifo.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_PIXELo.sh = 0;// Approximated illumination from non-important point lights#ifdef VERTEXLIGHT_ONo.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);#endifo.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// #elseUNITY_TRANSFER_FOG(o,o.pos); // pass fog coordinates to pixel shader// #endifreturn o;}

frag_surf 片段着色器

                fixed4 frag_surf (v2f_surf IN) : SV_Target{UNITY_SETUP_INSTANCE_ID(IN);// prepare and unpack dataInput surfIN;#ifdef FOG_COMBINED_WITH_TSPACEUNITY_EXTRACT_FOG_FROM_TSPACE(IN);#elif defined (FOG_COMBINED_WITH_WORLD_POS)UNITY_EXTRACT_FOG_FROM_WORLD_POS(IN);#elseUNITY_EXTRACT_FOG(IN);#endifUNITY_INITIALIZE_OUTPUT(Input,surfIN);surfIN.uv_MainTex.x = 1.0;surfIN.uv_MainTex = IN.pack0.xy;float3 worldPos = IN.worldPos.xyz;#ifndef USING_DIRECTIONAL_LIGHTfixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));#elsefixed3 lightDir = _WorldSpaceLightPos0.xyz;#endiffloat3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));#ifdef UNITY_COMPILER_HLSLSurfaceOutputStandard o = (SurfaceOutputStandard)0;#elseSurfaceOutputStandard o;#endifo.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 functionsurf (surfIN, o);// compute lighting & shadowing factorUNITY_LIGHT_ATTENUATION(atten, IN, worldPos)fixed4 c = 0;// Setup lighting environmentUnityGI 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 functionUnityGIInput 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;#elsegiInput.lightmapUV = 0.0;#endif#if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXELgiInput.ambient = IN.sh;#elsegiInput.ambient.rgb = 0.0;#endifgiInput.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_PROJECTIONgiInput.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;#endifLightingStandard_GI(o, giInput, gi);// realtime lighting: call lighting functionc += LightingStandard (o, worldViewDir, gi);UNITY_APPLY_FOG(_unity_fogCoord, c); // apply fogUNITY_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 alphahalf 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_HLSLSurfaceOutputStandard o = (SurfaceOutputStandard)0;#elseSurfaceOutputStandard 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 colorfixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;o.Albedo = c.rgb;// Metallic and smoothness come from slider variableso.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的uvfloat3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;#if UNITY_SHOULD_SAMPLE_SHhalf3 sh : TEXCOORD3; // SH 球谐#endifUNITY_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 shaderv2f_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);// #endifo.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_PIXELo.sh = 0;// Approximated illumination from non-important point lights#ifdef VERTEXLIGHT_ONo.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);#endifo.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// #elseUNITY_TRANSFER_FOG(o,o.pos); // pass fog coordinates to pixel shader// #endifreturn 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 factorUNITY_LIGHT_ATTENUATION(atten, IN, worldPos)// Setup lighting environmentUnityGI 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 functionUnityGIInput 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;#elsegiInput.lightmapUV = 0.0;#endif#if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXELgiInput.ambient = IN.sh;#elsegiInput.ambient.rgb = 0.0;#endifgiInput.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_PROJECTIONgiInput.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;#endifLightingStandard_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 enginefloat3 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_PROJECTIONfloat4 boxMax[2];float4 probePosition[2];#endif// HDR cubemap properties, use to decompress HDR texturefloat4 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.0half _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_REGISTERSstruct v2f_surf{// UNITY_POSITION(pos); = float4 pos :SV_POSITION;!!!!!!!!!!!!!!!!float4 pos :SV_POSITION;float2 pack0 : TEXCOORD0; // _MainTex  ,其中pack0 就是_MainTex的uvfloat3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;#if UNITY_SHOULD_SAMPLE_SHhalf3 sh : TEXCOORD3; // SH 球谐#endifUNITY_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 shaderv2f_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);// #endifo.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_PIXELo.sh = 0;// Approximated illumination from non-important point lights#ifdef VERTEXLIGHT_ONo.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);#endifo.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// #elseUNITY_TRANSFER_FOG(o,o.pos); // pass fog coordinates to pixel shader// #endifreturn o;}
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------// fragment shaderfixed4 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;// #endiffloat3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//将SurfaceOutputStandard的数据填充完整。SurfaceOutputStandard o;UNITY_INITIALIZE_OUTPUT(SurfaceOutputStandard,o);// #ifdef UNITY_COMPILER_HLSL//     SurfaceOutputStandard o = (SurfaceOutputStandard)0;// #else//     SurfaceOutputStandard o;// #endiffixed4 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 factorUNITY_LIGHT_ATTENUATION(atten, IN, worldPos)// Setup lighting environmentUnityGI 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 functionUnityGIInput 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;#elsegiInput.lightmapUV = 0.0;#endif#if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXELgiInput.ambient = IN.sh;#elsegiInput.ambient.rgb = 0.0;#endifgiInput.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_PROJECTIONgiInput.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;#endifLightingStandard_GI(o, giInput, gi);
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------//PBR的核心计算,基于物理着色,BRDF的相关计算// realtime lighting: call lighting functionfixed4 c = LightingStandard (o, worldViewDir, gi);UNITY_APPLY_FOG(_unity_fogCoord, c); // apply fog// Alpha值为1.0UNITY_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 0float m = PerceptualRoughnessToRoughness(perceptualRoughness); // m is the real roughness parameterconst 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.pdfn /= 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.htmlperceptualRoughness = 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);//tex2Dlodreturn 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_OFFspecular = unity_IndirectSpecColor.rgb;#elsehalf3 env0 = Unity_GlossyEnvironment_MY (UNITY_PASS_TEXCUBE(unity_SpecCube0), data.probeHDR[0], glossIn);#ifdef UNITY_SPECCUBE_BLENDINGconst float kBlendFactor = 0.99999;float blendLerp = data.boxMin[0].w;UNITY_BRANCHif (blendLerp < kBlendFactor){#ifdef UNITY_SPECCUBE_BOX_PROJECTIONglossIn.reflUVW = BoxProjectedCubemapDirection (originalReflUVW, data.worldPos, data.probePosition[1], data.boxMin[1], data.boxMax[1]);#endifhalf3 env1 = Unity_GlossyEnvironment_MY (UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1,unity_SpecCube0), data.probeHDR[1], glossIn);specular = lerp(env1, env0, blendLerp);}else{specular = env0;}#elsespecular = env0;#endif#endifreturn 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 光照模型 GIinline 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_MYgi = UnityGlobalIllumination_MY(data, s.Occlusion, s.Normal);#elseUnity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup_MY(s.Smoothness, data.worldViewDir, s.Normal, lerp(unity_ColorSpaceDielectricSpec.rgb, s.Albedo, s.Metallic));// 返回gigi = 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 200Pass {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_SHhalf3 sh : TEXCOORD3;#endifUNITY_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_PIXELo.sh = 0;#ifdef VERTEXLIGHT_ONo.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);#endifo.sh = ShadeSHPerVertex (worldNormal, o.sh);#endifUNITY_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_PIXELgiInput.ambient = IN.sh;#elsegiInput.ambient.rgb = 0.0;#endifgiInput.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_CGINChalf3 Unity_GlossyEnvironment_MY (UNITY_ARGS_TEXCUBE(tex), half4 hdr, Unity_GlossyEnvironmentData glossIn){half perceptualRoughness = glossIn.roughness /* perceptualRoughness */ ;#if 0float m = PerceptualRoughnessToRoughness(perceptualRoughness); // m is the real roughness parameterconst 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.pdfn /= 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.htmlperceptualRoughness = 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)#elseperceptualRoughness = perceptualRoughness*(1.7 - 0.7*perceptualRoughness);#endifhalf mip = perceptualRoughnessToMipmapLevel(perceptualRoughness);half3 R = glossIn.reflUVW;half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(tex, R, mip);//tex2Dlodreturn DecodeHDR(rgbm, hdr);}inline half3 UnityGI_IndirectSpecular_MY(UnityGIInput data, half occlusion, Unity_GlossyEnvironmentData glossIn){half3 specular;#ifdef _GLOSSYREFLECTIONS_OFFspecular = unity_IndirectSpecColor.rgb;#elsehalf3 env0 = Unity_GlossyEnvironment_MY (UNITY_PASS_TEXCUBE(unity_SpecCube0), data.probeHDR[0], glossIn);#ifdef UNITY_SPECCUBE_BLENDINGconst float kBlendFactor = 0.99999;float blendLerp = data.boxMin[0].w;UNITY_BRANCHif (blendLerp < kBlendFactor){#ifdef UNITY_SPECCUBE_BOX_PROJECTIONglossIn.reflUVW = BoxProjectedCubemapDirection (originalReflUVW, data.worldPos, data.probePosition[1], data.boxMin[1], data.boxMax[1]);#endifhalf3 env1 = Unity_GlossyEnvironment_MY (UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1,unity_SpecCube0), data.probeHDR[1], glossIn);specular = lerp(env1, env0, blendLerp);}else{specular = env0;}#elsespecular = env0;#endif#endifreturn 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_BUFFERSgi = UnityGlobalIllumination_MY(data, s.Occlusion, s.Normal);#elseUnity_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.rhkb.cn/news/145016.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zygisk-IL2CppDumper对抗方案

众所周知&#xff0c;Unity引擎中有两种脚本编译器&#xff0c;分别是 Mono 和 IL2CPP 。这两种脚本编译器各有优势&#xff0c;同时也存在一些安全性问题&#xff0c;本文将从游戏安全角度对其进行分析并提供对策。 Mono 是由跨平台的开源.NET 实现&#xff0c;它允许开发者使…

Unity如何实现TreeView

前言 最近有一个需求,需要实现一个TreeView的试图显示,开始我一直觉得这么通用的结构,肯定有现成的UI组件或者插件可以使用,结果,找了好久,都没有找到合适的插件,有两个效果差强人意。 最后在回家的路上突然灵光一闪,想到了一种简单的实现方式,什么插件都不用,仅使用…

《学术小白学习之路12》进阶-基于Python实现中文文本的DTM主题动态模型构建

《学术小白学习之路》基于Python实现中文文本的DTM主题动态模型构建 一、数据选择二、数据预处理三、输入数据ID映射词典构建四、文档加载成构造语料库五、DTM模型构建与结果分析六、结果进行保存七、保存模型一、数据选择 所选取的数据集是论文摘要,作为实验数据集,共计12条…

从1开始的Matlab(快速入门)

MATLAB软件版本&#xff1a;MATLAB R2016b 本文是博主从零开始学Matlab的记录&#xff0c;适合第一次接触Matlab的同学阅读。 一、基础介绍 1.1界面认识 1.2变量命名 注&#xff1a;Matlab中的注释 %% 独占一行的注释&#xff08;有上下横线分割&#xff09; % 普通注释 …

react项目优化

随着项目体积增大&#xff0c;打包的文件体积会越来越大&#xff0c;需要优化&#xff0c;原因无非就是引入的第三方插件比较大导致&#xff0c;下面我们先介绍如何分析各个文件占用体积的大小。 1.webpack-bundle-analyzer插件 如果是webpack作为打包工具的项目可以使用&…

Vivado与Notepad++关联步骤

填写内容 先看"关联步骤"再看此处&#xff1a; 在“editor”栏中填写 Notepad的路径&#xff0c;并加上[file name] -n[line number]&#xff0c; 这里我的 Notepad 的路径为 C:/Program Files (x86)/Notepad/notepad.exe &#xff1b; 故这里我就填上以下内容即可…

xxl-job 2.2之后版本高版本executor未授权访问漏洞

xxl-job 低版本executor未授权访问 低版本的executor未授权访问漏洞是 POST /run HTTP/1.1 Host: your-ip:9999 Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like G…

rabbitMQ死信队列快速编写记录

文章目录 1.介绍1.1 什么是死信队列1.2 死信队列有什么用 2. 如何编码2.1 架构分析2.2 maven坐标2.3 工具类编写2.4 consumer1编写2.5 consumer2编写2.6 producer编写 3.整合springboot3.1 架构图3.2 maven坐标3.3 构建配置类&#xff0c;创建exchange&#xff0c;queue&#x…

【Leetcode】 450. 删除二叉搜索树中的节点

给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;删除节点可分为两个步骤&#xff1a; 首先…

“童”趣迎国庆 安全“童”行-柿铺梁坡社区开展迎国庆活动

“金秋十月好心境&#xff0c;举国欢腾迎国庆。”国庆节来临之际&#xff0c;为进一步加强梁坡社区未成年人爱国主义教育&#xff0c;丰富文化生活&#xff0c;营造热烈喜庆、文明和谐的节日氛围。9月24日上午&#xff0c;樊城区柿铺街道梁坡社区新时代文明实践站联合襄阳市和时…

Spring IOC(控制反转)与DI(依赖注入)

定义 IOC(Inversion of Control)&#xff0c;即控制反转&#xff1a;对象的创建控制权不再由程序来执行&#xff0c;而是交由给Spring容器处理。简单的说程序不需要进行new操作&#xff0c;对象直接由Spring容器自动创建。 DI(Dependency Injection)&#xff0c;即依赖注入&am…

阿木实验室PrometheusV1.1安装+Ubuntu 20.04

1. 安装ros-noetic 2. 安装Mavros包 sudo apt-get install ros-noetic-mavros ros-noetic-mavros-extras3. GeographicLib wget https://raw.githubusercontent.com/mavlink/mavros/master/mavros/scripts/install_geographiclib_datasets.sh这里可以使用代理 &#xff1a;wg…

9.30小任务

消息队列实现进程之间通信方式 实现了父子进程之间的通信 #include <myhead.h>//消息结构体 typedef struct {long msgtype; //消息类型char data[1024]; //消息正文 }Msg_ds;#define SIZE sizeof(Msg_ds)-sizeof(long) //正文大小int main(int arg…

Bug:elementUI样式不起作用、Vue引入组件报错not found等(Vue+ElementUI问题汇总)

前端问题合集&#xff1a;VueElementUI 1. Vue引用Element-UI时&#xff0c;组件无效果解决方案 前提&#xff1a; 已经安装好elementUI依赖 //安装依赖 npm install element-ui //main.js中导入依赖并在全局中使用 import ElementUI from element-ui Vue.use(ElementUI)如果此…

idea环境下如何打包可运行jar?

工作中有时候偶尔写一些工具类、小程序&#xff0c;可是java程序员制作一个可运行jar实在折腾&#xff0c;利用idea开发环境&#xff0c;可以快速打包自己的可运行jar。具体怎么操作呢&#xff1f; 创建一个空白的java项目并完成自己的程序开发 完成java代码&#xff1a; /**…

(Vue3)defineOptions、defineModels Pinia及持久化

Vue3.3新特性defineOptions v-model和defineModel 开启特性vite.config.js中加配置 重启架子&#xff08;试验性质&#xff09;npm run dev Pinia Vue最新的状态管理工具&#xff0c;代替Vuex Pinia配置创建项目时自动添加 安装 npm install pinia 创建一个 pinia 实例 (根 s…

Bluespec SytemVerilog 握手协议接口转换

01、引言 由于接口控制信号上的差异&#xff0c;要实现Bluespec SystemVerilog(BSV)生成的代码和外部Verilog代码之间的正确交互是一件比较麻烦同时容易出错的事情。在BSV中, 模块之间的交互都是基于Action或ActionValue这两类method完成。下图展示了使用BSV设计的某一模块的接…

8.2 Jmeter if控制器使用

前提&#xff1a;jmeter脚本需要用到if控制器&#xff0c;if判断如果查询不到&#xff0c;则去新增。 1、添加if控制器 线程组-->逻辑控制器-->如果(if)控制器 1&#xff09;、Expression (must evaluate to true or false) &#xff1a;表达式&#xff08;值必须是tru…

数据结构算法--6 希尔排序和计数排序

希尔排序 希尔排序与插入排序原理相同&#xff0c;希尔排序是一种分组插入排序算法 > 首先取一个整数d1n/2&#xff0c;将元素分为d1个组&#xff0c;每组相邻两元素之间距离为d1&#xff0c;在各组内之间插入排序。 > 取第二个整数d2n/2&#xff0c;重复上述分组排序…

HTML——列表,表格,表单内容的讲解

文章目录 一、列表1.1无序&#xff08;unorder&#xff09;列表1.2 有序&#xff08;order&#xff09;列表1.3 定义列表 二、表格**2.1 基本的表格标签2.2 演示 三、表单3.1 form元素3.2 input元素3.2.1 单选按钮 3.3 selcet元素 基础部分点击&#xff1a; web基础 一、列表 …