【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.xdnf.cn/news/146214.html

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

相关文章

web:[极客大挑战 2019]PHP

题目 点进页面显示如下 根据页面提示&#xff0c;这个网站有备份文件&#xff0c;备份文件一般是bak文件格式&#xff0c;用dirsearch扫描 访问之后下载了一个文件 里面都是一些代码 在index.php中发现了一个类的文件&#xff0c;一个get传参&#xff0c;然后将传进的值进行反序…

Java性能调优必备知识学习路线

性能调优是Java开发中一个非常重要的环节&#xff0c;它可以帮助我们提高系统的性能、稳定性、可靠性和用户体验&#xff0c;从而提高用户体验和企业竞争力。 目录 一、为什么要学习Java性能调优&#xff1f; 二、如何做好性能调优&#xff1f; 2.1 扎实的计算机基础 2.2 …

Redis与分布式-集群搭建

接上文 Redis与分布式-哨兵模式 1. 集群搭建 搭建简单的redis集群&#xff0c;创建6个配置&#xff0c;开启集群模式&#xff0c;将之前配置过的redis删除&#xff0c;重新复制6份 针对主节点redis 1&#xff0c;redis 2&#xff0c;redis 3都是以上修改内容&#xff0c;只是…

集合-ArrayList源码分析(面试)

系列文章目录 1.集合-Collection-CSDN博客​​​​​​ 2.集合-List集合-CSDN博客 3.集合-ArrayList源码分析(面试)_喜欢吃animal milk的博客-CSDN博客 目录 系列文章目录 前言 一 . 什么是ArrayList? 二 . ArrayList集合底层原理 总结 前言 大家好,今天给大家讲一下Arra…

最优化:建模、算法与理论(最优性理论

第五章 最优性理论 在实际中最优化问题的形式多种多样&#xff0c;给定一类具体的优化问题&#xff0c;我们首先需要分析其解的存在性。如果优化问题的解存在&#xff0c;再考虑如何设计算法求出最优解&#xff0c;一般的非凸优化问题可能存在很多局部极小解&#xff0c;但其往…

IO流 之 缓冲流(字节缓冲流和字符缓冲流)

缓冲流对原始流进行了包装&#xff0c;以提高原始流读写数据的性能。 字节缓冲流&#xff08;BufferedInputStream和BufferedOutputStream&#xff09; 字节缓冲流在内存中提供了一个默认为8kb的区域&#xff0c;用于缓冲&#xff0c;当流开始时&#xff0c;先读取一个8kb的内…

CCF CSP认证 历年题目自练Day18

CCF CSP认证 历年题目自练Day18 题目一 试题编号&#xff1a; 201809-1 试题名称&#xff1a; 卖菜 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 256.0MB 问题描述&#xff1a; 问题描述   在一条街上有n个卖菜的商店&#xff0c;按1至n的顺序排成一排&#xff0c;这…

Spring的注解开发-非自定义Bean的配置

非自定义Bean注解开发 非自定义Bean不能象自定义Bean一样使用Component注解及其衍生注解进行管理&#xff0c;非自定义Bean要通过工厂的方式进行实例化&#xff0c;使用Bean标注即可&#xff0c;Bean的属性为beanName&#xff0c;使用Bean注解作用在方法中&#xff0c;通过定义…

视觉人机器视觉线下培训遵循十大原则

1.​上课期间&#xff0c;自习时间没收手机&#xff0c;偷偷使用手机&#xff0c;将会被通报严重批评。 2.完善的教学设备&#xff0c;与具备现场落地设备要求。 3.教学与实操结合&#xff0c;老师教学的同时&#xff0c;要求你按照老师的效果&#xff0c;进行复现&#xff0…

Hello World!1分钟配置好你的Go环境

目录 一、简介为什么选择Golang&#xff1f;Golang与其他语言的对比核心特性应用场景社区和生态系统性能标准企业级应用 二、环境要求操作系统WindowsLinux/UnixmacOS 硬件需求其他依赖软件异常情况和处理方法 三、下载和安装GolangWindows系统使用官方安装包使用Chocolatey&am…

vue造轮子完整指南--npm组件包开发步骤

一、项目包文件的创建和初始化。 1. 新建项目包。 vue create <Project Name> //用于发布npm包的项目文件名 ps:一般选择自定义&#xff0c;然后不需要Vuex和Router&#xff0c;其他选项按自己实际情况选择安装即可。 2.修改原始src文件名、新增组件项目存放文件和修改…

小白继续深入学习C++

第1节 指针的基本概念 1、变量的地址&#xff1a; 变量是内存地址的简称&#xff0c;在C中&#xff0c;每定义一个变量&#xff0c;系统就会给变量分配一块内存&#xff0c;内存是有地址的。 C用运算符&获取变量在内存中的起始地址。 语法&#xff1a; &变…

【MySQL进阶】--- 存储引擎的介绍

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】&#x1f388; 本专栏旨在分享学习MySQL的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 一、什么…

[Spring] Spring5——IOC 简介(二)

目录 六、工厂 Bean&#xff08;Factory&#xff09; 1、普通 bean 2、工厂 bean 3、示例 七、Bean 的作用域 1、单例和多例 2、如何设置为单实例或多实例 八、Bean 的生命周期 1、生命周期 2、生命周期示例 3、Bean 的后置处理器 4、后置处理器示例 九、XML 的自…

c# 委托 事件 lambda表达式

委托 C/C中的函数指针实例&#xff1a; typedef int (*Calc)(int a, int b); //这里必须加括号 int Add(int a, int b) {return a b; } int Sub(int a, int b) {return a - b; } int main() {int x 100;int y 200;int z 0;Calc funcPoint1 &Add;Calc funcPoint2 &am…

全国排名前三的直播公司无锋科技入驻天府蜂巢成都直播产业基地

最近&#xff0c;全国排名前三的直播公司——无锋科技&#xff0c;正式宣布入驻位于成都的天府蜂巢直播产业基地&#xff0c;这一消息引起了业内人士的高度关注。成都直播产业基地一直是中国直播产业的重要地标之一&#xff0c;其强大的技术和资源优势为众多直播公司提供了广阔…

26 docker前后端部署

[参考博客]((257条消息) DockerNginx部署前后端分离项目(SpringBootVue)的详细教程_在docker中安装nginx实现前后端分离_这里是杨杨吖的博客-CSDN博客) (DockerNginx部署前后端分离项目(SpringBootVue)) 安装docker # 1、yum 包更新到最新 yum update # 2、安装需要的软件包…

csgo盲盒支付接口如何申请?

csgo盲盒支付接口如何申请&#xff1f;个人认为没什么特别难懂的&#xff01; 第一点&#xff1a;确定网站的基本功能&#xff01;每个网站的玩法大概都是一样的&#xff0c;无非是拆箱盲盒&#xff0c;ROLL房间、决斗、货物、生存和更换合同&#xff0c;然后有积分购物中心&am…

vue 实现数字验证码功能

需求&#xff1a;写了一个 手机发送验证码后 输入固定验证码的功能 封装成一个组件,如下: <template><div class"conts"><div class"box"><div class"code_list"><div :class"[ code_item, hideIndex 0 ? co…

Flutter笔记:滚动之-无限滚动与动态加载的实现

Flutter笔记 无限滚动与动态加载的实现 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/133342307 本文还…