URP built-in Lit.Shader file ForwardLit Pass parsing

Article directory

  • Lit main file
    • Properties
    • SubShader code block
      • FormardLit
        • Label
        • Compilation command
        • Declare keywords
          • Material Keywords
          • Rendering pipeline keywords Universal Pipeline keywords
          • Unity defined keywords Unity defined keywords
        • Contains directives
      • 1. LitInput.hlsl
        • (1) Attribute variables
        • (2) Texture sampling function
        • (3) AO sampling function
        • (4) Surface data initialization function
          • SurfaceData: fragment data, in `SurfaceData.hlsl`
          • SurfaceInput: Function to get SurfaceData, in `SurfaceInput.hlsl`
        • (4) Surface data initialization function
      • 2. LitForwardPass.hlsl
        • (1) Fragment function input structure
        • Reference library: Common.hlsl, common library (including: specifications, real definitions, common functions)
          • Commonly used functions
        • Reference library: Input.hlsl
          • InputData structure
          • Constant Buffers
          • Macros for transformation matrices
        • (2) Input data initialization function
        • Reference library: SpaceTransform.hlsl
        • (3) Vertex function
          • Part One: Initialization Part
          • Part 2: Initializing the structure for calling
            • Supplement: Core.hlsl
            • Added: ShaderVariablesFunctions.hlsl
          • Part 3: Obtain calculation-related data
        • (4) Fragment function
          • Part One: Initialization Data
          • Part 2: Using this data to calculate surface shading
          • Part Three: Fog Effect
          • Part 4: Whether it is transparent (“_Surface”)
  • Summary of function and macro definitions
  • postscript

Lit main file

Properties

[MainTexture] Main texture, which can be accessed using Material.mainTexture
[MainColor] Main color, which can be accessed using Material.color
[ToggleOff] makes the numeric type attribute appear as a switch style on the material panel, and can declare the keyword in the compilation directive (uppercase attribute name + OFF)
[Toggle]Enables numeric type attributes to be displayed as switch styles on the material panel, and can declare keywords in the compilation directive (uppercase attribute name + ON)

SubShader code block

Only SubShaders marked with the following tags can run in URP

 "RenderPipeline" = "UniversalPipeline"

SubShader contains a total of 5 tags:

  • FormardLit

FormardLit

tag

Tags{"LightMode" = "UniversalForward"}

Compile command

Shader is not compiled for gles gles3 glcore feature level rendering platform, use version 4.5

#pragma exclude_renderers gles gles3 glcore
#pragma target 4.5
Declare keywords

Keywords are divided into three categories:

  • Material Keywords
  • Rendering pipeline keywords Universal Pipeline keywords
  • Unity defined keywords Unity defined keywords
Material Keywords
//----------------------------------------
// Material Keywords
#pragma shader_feature_local _NORMALMAP // When a normal map is added, pass in the keyword
#pragma shader_feature_local _PARALLAXMAP // Disparity map
#pragma shader_feature_local _RECEIVE_SHADOWS_OFF // Accept shadows when turned off
#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED // ?
#pragma shader_feature_local_fragment _SURFACE_TYPE_TRANSPARENT //Surface type transparent ?
#pragma shader_feature_local_fragment _ALPHATEST_ON // When transparent clipping is turned on~
#pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON // The blending mode is Premultiply
#pragma shader_feature_local_fragment _EMISSION // Turn on self-illumination
#pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP // Metallic workflow uses metal maps, or specular workflow uses specular maps
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A // When the smoothness data selects Specular Alpha
#pragma shader_feature_local_fragment _OCCLUSIONMAP // When adding AO map
#pragma shader_feature_local_fragment _SPECULARHIGHLIGHTS_OFF // When specular highlight reflection is turned off
#pragma shader_feature_local_fragment _ENVIRONMENTREFLECTIONS_OFF // When environment reflection is turned off
#pragma shader_feature_local_fragment _SPECULAR_SETUP // When the highlight workflow is selected
Rendering pipeline keywords Universal Pipeline keywords

As an overall pipeline setup
Just set it under the RenderPipelineAsset resource

//----------------------------------------
// Universal Pipeline keywords
// No shadow, shadow, cascade shadow, screen space shadow
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
// No additional lighting, additional vertex lighting, additional fragment lighting
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
// No additional light shadows, enable additional light shadows
#pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
// Light probe blending
#pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING
// Box projection reflection probe
#pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION
// soft shadow
#pragma multi_compile_fragment _ _SHADOWS_SOFT
//SSAO
#pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
// Other weird parameters
#pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3
#pragma multi_compile_fragment _ _LIGHT_LAYERS
#pragma multi_compile_fragment _ _LIGHT_COOKIES
#pragma multi_compile _ _CLUSTERED_RENDERING

Unity defined keywords Unity defined keywords

The keywords in this part are related to scene lighting, in the Lighting settings panel

//----------------------------------------
// Unity defined keywords
#pragma multi_compile _ LIGHTMAP_SHADOW_MIXING // Light map shadow mixing
#pragma multi_compile _ SHADOWS_SHADOWMASK //
#pragma multi_compile _ DIRLIGHTMAP_COMBINED //Whether to use Directional mode lighting baking
#pragma multi_compile _ LIGHTMAP_ON //Whether to enable light map
#pragma multi_compile _ DYNAMICLIGHTMAP_ON //Whether to enable dynamic light maps
#pragma multi_compile_fog //Whether to enable fog effect
#pragma multi_compile_fragment _ DEBUG_DISPLAY //
Contains directives
//-----------------------------------------
//GPU Instancing
#pragma multi_compile_instancing // Make Shader support GPU instances
#pragma instancing_options renderinglayer
#pragma multi_compile _ DOTS_INSTANCING_ON

#pragma vertex LitPassVertex
#pragma fragment LitPassFragment

#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitForwardPass.hlsl"

1. LitInput.hlsl

Include header files:

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ParallaxMapping.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DBuffer.hlsl"
(1) Attribute variable

constant buffer

CBUFFER_START(UnityPerMaterial)
...can be used in Shaders
CBUFFER_END

texture

TEXTURE2D(_ParallaxMap); SAMPLER(sampler_ParallaxMap);

SAMPLER can be used in other ways

  • SAMPLER(filter_wrap)
  • SAMPLER(filter_wrapU_wrapV)
    • filter: point, linear, triLinear
    • wrap: clamp, repeat, mirror, mirrorOnce
(2) Texture sampling function

Sampling metallicity or specularity returns half4 specGloss

half4 SampleMetallicSpecGloss(float2 uv, half albedoAlpha)
(3) AO sampling function

Returns the sampling result of the AO map

half SampleOcclusion(float2 uv)
(4) Surface data initialization function
inline void InitializeStandardLitSurfaceData(float2 uv, out SurfaceData outSurfaceData)

Surface data initialization function requires SurfaceData

SurfaceData: fragment data, in SurfaceData.hlsl
struct SurfaceData
{<!-- -->
    half3 albedo; //Color (albedo)
    half3 specular; //Specular reflection
    half metallic; //metallicity
    half smoothness; //smoothness
    half3 normalTS; //Normal TS (Tile display Tiling, offset Offset)
    half3 emission; //Self-luminous
    half occlusion; //occlusion value
    half alpha; //transparency
    half clearCoatMask; //Transparent layer Mask
    half clearCoatSmoothness; //--------
};
SurfaceInput: Function to obtain SurfaceData, in SurfaceInput.hlsl

Included libraries:

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceData.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"

Texture:

TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); float4 _BaseMap_TexelSize; float4 _BaseMap_MipInfo;
TEXTURE2D(_BumpMap); SAMPLER(sampler_BumpMap);
TEXTURE2D(_EmissionMap); SAMPLER(sampler_EmissionMap);

Function:
Transparency function: Get the transparent attribute, and decide whether to turn on culling according to the _ALPHATEST_ON macro, and culling it.

//Parameters: Alpha channel of Albedo texture (BaseMap), base color (BaseColor), clipping value
half Alpha(half albedoAlpha, half4 color, half cutoff)

Albedo texture sampling function:

//Texture coordinates texture variables sampler
half4 SampleAlbedoAlpha(float2 uv, TEXTURE2D_PARAM(albedoAlphaMap, sampler_albedoAlphaMap))
{<!-- -->
    return half4(SAMPLE_TEXTURE2D(albedoAlphaMap, sampler_albedoAlphaMap, uv));
}

Normal map sampling function

half3 SampleNormal(float2 uv, TEXTURE2D_PARAM(bumpMap, sampler_bumpMap), half scale = half(1.0))

Self-illumination map sampling function

half3 SampleEmission(float2 uv, half3 emissionColor, TEXTURE2D_PARAM(emissionMap, sampler_emissionMap))

Now we return to the surface data initialization function

(4) Surface data initialization function

Initialize the variables in the SurfaceData structure and output it.

inline void InitializeStandardLitSurfaceData(float2 uv, out SurfaceData outSurfaceData)
{<!-- -->
// Get the texture alpha value
    half4 albedoAlpha = SampleAlbedoAlpha(uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap));
    // Mix the alpha value of the coefficient and eliminate it
    outSurfaceData.alpha = Alpha(albedoAlpha.a, _BaseColor, _Cutoff);

// Sample specular or metallic values
    half4 specGloss = SampleMetallicSpecGloss(uv, albedoAlpha.a);
    //Save color value
    outSurfaceData.albedo = albedoAlpha.rgb * _BaseColor.rgb;

//Save the highlight value or metallic value
#if _SPECULAR_SETUP
    outSurfaceData.metallic = half(1.0);
    outSurfaceData.specular = specGloss.rgb;
#else
    outSurfaceData.metallic = specGloss.r;
    outSurfaceData.specular = half3(0.0, 0.0, 0.0);
#endif
// smoothness
    outSurfaceData.smoothness = specGloss.a;
    // normal
    outSurfaceData.normalTS = SampleNormal(uv, TEXTURE2D_ARGS(_BumpMap, sampler_BumpMap), _BumpScale);
    outSurfaceData.occlusion = SampleOcclusion(uv);
    outSurfaceData.emission = SampleEmission(uv, _EmissionColor.rgb, TEXTURE2D_ARGS(_EmissionMap, sampler_EmissionMap));

#if defined(_CLEARCOAT) || defined(_CLEARCOATMAP)
    half2 clearCoat = SampleClearCoat(uv);
    outSurfaceData.clearCoatMask = clearCoat.r;
    outSurfaceData.clearCoatSmoothness = clearCoat.g;
#else
    outSurfaceData.clearCoatMask = half(0.0);
    outSurfaceData.clearCoatSmoothness = half(0.0);
#endif

#if defined(_DETAIL)
    half detailMask = SAMPLE_TEXTURE2D(_DetailMask, sampler_DetailMask, uv).a;
    float2 detailUv = uv * _DetailAlbedoMap_ST.xy + _DetailAlbedoMap_ST.zw;
    outSurfaceData.albedo = ApplyDetailAlbedo(detailUv, outSurfaceData.albedo, detailMask);
    outSurfaceData.normalTS = ApplyDetailNormal(detailUv, outSurfaceData.normalTS, detailMask);
#endif
}

2. LitForwardPass.hlsl

(1) Fragment function input structure
struct Varyings
{<!-- -->
// direct parameters
    float2 uv : TEXCOORD0;
float3 normalWS : TEXCOORD2;
// Texture coordinates of light map: float2 lmName : TEXCOORD##index
// Or texture coordinates of spherical harmonics? :half3 shName : TEXCOORD##index
// Need to pass in (light map name, spherical harmonic function name, texture coordinate index TEXCOORD8)
DECLARE_LIGHTMAP_OR_SH(staticLightmapUV, vertexSH, 8);
float4 positionCS : SV_POSITION;

// REQUIRES_WORLD_SPACE_POS_INTERPOLATOR? ? ? ? ? ? ? ? ?
#if defined(REQUIRES_WORLD_SPACE_POS_INTERPOLATOR)
    float3 positionWS : TEXCOORD1;
#endif

#if defined(REQUIRES_WORLD_SPACE_TANGENT_INTERPOLATOR)
    half4 tangentWS : TEXCOORD3; // xyz: tangent, w: sign
#endif

#ifdef _ADDITIONAL_LIGHTS_VERTEX
    half4 fogFactorAndVertexLight : TEXCOORD5; // x: fogFactor, yzw: vertex light
#else
    half fogFactor : TEXCOORD5;
#endif

#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
    float4 shadowCoord : TEXCOORD6;
#endif

#if defined(REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR)
    half3 viewDirTS : TEXCOORD7;
#endif

    
#ifdef DYNAMICLIGHTMAP_ON
    float2 dynamicLightmapUV : TEXCOORD9; // Dynamic lightmap UVs
#endif

    
    UNITY_VERTEX_INPUT_INSTANCE_ID
    UNITY_VERTEX_OUTPUT_STEREO
};
Referenced library: Common.hlsl, common library (including: specifications, real definitions, common functions)
Commonly used functions
real DegToRad(real deg)//Angle to radians
real RadToDeg(real rad)//radian angle
float Length2(float3 v)//returns the square of the vector length
real3 SafeNormalize(float3 inVec)//Returns a standardized 3-dimensional vector
real SafeDiv(real numer, real denom)//return numer/denom

Reference library: Input.hlsl
InputData structure
struct InputData
{<!-- -->
    float3 positionWS;
    float4 positionCS;
    float3 normalWS;
    half3 viewDirectionWS;
    float4 shadowCoord; //UV in shadow map
    half fogCoord; //The level of fog
    half3 vertexLighting; //Vertex lighting (Additional Light)
    half3 bakedGI; //Global illumination (light map or spherical harmonic function calculation)
    float2 normalizedScreenSpaceUV;
    half4 shadowMask;
    half3x3 tangentToWorld; //Normal transformation to the TBN matrix of world space, related to the model matrix
    #if defined(DEBUG_DISPLAY)
    half2 dynamicLightmapUV;
    half2 staticLightmapUV;
    float3 vertexSH;
    half3 brdfDiffuse;
    half3 brdfSpecular;
    float2 uv;
    uint mipCount;
    float4 texelSize;
    float4 mipInfo;
    #endif
};
Constant Buffers

Some other variable definitions

half4 _GlossyEnvironmentColor;//Environment reflection color
half4 _SubtractiveShadowColor;// shadow color
half4 _GlossyEnvironmentCubeMap_HDR;
TEXTURECUBE(_GlossyEnvironmentCubeMap);
SAMPLER(sampler_GlossyEnvironmentCubeMap);
#define _InvCameraViewProj unity_MatrixInvVP
float4 _ScaledScreenParams;
float4 _MainLightPosition; // Main light source position
half4 _MainLightColor; // Main light color
half4 _MainLightOcclusionProbes; // The main light source blocks the sneaker probe? ? ?
uint _MainLightLayerMask; // Main light source layer mask
half4 _AmbientOcclusionParam;
half4 _AdditionalLightsCount;
Transformation matrix macro
#define UNITY_MATRIX_M unity_ObjectToWorld
#define UNITY_MATRIX_I_M unity_WorldToObject
#define UNITY_MATRIX_V unity_MatrixV
#define UNITY_MATRIX_I_V unity_MatrixInvV
#define UNITY_MATRIX_P OptimizeProjectionMatrix(glstate_matrix_projection)
#define UNITY_MATRIX_I_P unity_MatrixInvP
#define UNITY_MATRIX_VP unity_MatrixVP
#define UNITY_MATRIX_I_VP unity_MatrixInvVP
#define UNITY_MATRIX_MV mul(UNITY_MATRIX_V, UNITY_MATRIX_M)
#define UNITY_MATRIX_T_MV transpose(UNITY_MATRIX_MV)
#define UNITY_MATRIX_IT_MV transpose(mul(UNITY_MATRIX_I_M, UNITY_MATRIX_I_V))
#define UNITY_MATRIX_MVP mul(UNITY_MATRIX_VP, UNITY_MATRIX_M)
#define UNITY_PREV_MATRIX_M unity_MatrixPreviousM
#define UNITY_PREV_MATRIX_I_M unity_MatrixPreviousMI
(2) Input data initialization function

To initialize the InputData structure, the function needs to pass in the Varyings structure and the tangent space normal, and then output the InputData structure.

void InitializeInputData(Varyings input, half3 normalTS, out InputData inputData)
 inputData = (InputData)0;//Initialization (this writing method is a syntax structure)
Reference library: SpaceTransform.hlsl

Contains all functions related to spatial transformation

(3) Vertex function
Part 1: Initialization part
Varyings output = (Varyings)0;

UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);

Initialize the output structure.
Enable the vertex shader to obtain the GPU instance ID
Pass the instance ID to the output structure
Vertex operations for VR platforms (VR platforms are generated by two cameras)

Part 2: Initializing the structure for calling

Two structures are declared and initialized.
These two structures are defined in Core.hlsl, and the initialization function is defined in ShaderVariablesFunctions.hlsl. The purpose is to pass in a required variable and get all the related variables. Variables are convenient for users to call directly when writing code.

VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);

// normalWS and tangentWS already normalize.
// this is required to avoid skewing the direction during interpolation
// also required for per-vertex lighting and SH evaluation
VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);
Supplement: Core.hlsl
// Structs
struct VertexPositionInputs
{<!-- -->
    float3 positionWS; // World space position
    float3 positionVS; // View space position
    float4 positionCS; // Homogeneous clip space position
    float4 positionNDC;// Homogeneous normalized device coordinates
};

struct VertexNormalInputs
{<!-- -->
    real3 tangentWS; // World space tangent
    real3 bitangentWS; // World space secondary tangent
    float3 normalWS; // World space normal
};
Supplement: ShaderVariablesFunctions.hlsl
VertexPositionInputs GetVertexPositionInputs(float3 positionOS)
VertexNormalInputs GetVertexNormalInputs(float3 normalOS)//Only fill normalWS
VertexNormalInputs GetVertexNormalInputs(float3 normalOS, float4 tangentOS)//Fill three tangents
...
Part 3: Obtain calculation-related data

calculate data:

half3 vertexLight = VertexLighting(vertexInput.positionWS, normalInput.normalWS);
//_FOG_FRAGMENT
half fogFactor = ComputeFogFactor(vertexInput.positionCS.z);
//REQUIRES_WORLD_SPACE_TANGENT_INTERPOLATOR || REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR
real sign = input.tangentOS.w * GetOddNegativeScale();
half4 tangentWS = half4(normalInput.tangentWS.xyz, sign);
//REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR
half3 viewDirWS = GetWorldSpaceNormalizeViewDir(vertexInput.positionWS);
half3 viewDirTS = GetViewDirectionTangentSpace(tangentWS, output.normalWS, viewDirWS);
  • vertexLight: additional light illumination value, obtained by accumulating multiple lights (after distance attenuation and angle attenuation). The VertexLighting() function is defined in Lighting.hlsl.
  • fogFactor: fog effect factor, the farther away, the larger. The ComputeFogFactor() function is defined in the ShaderVariablesFunctions.hlsl file. The function needs to pass in the depth value Z.

save data:

output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);//TRANSFORM_TEX==> scale & amp; & amp; offset
output.normalWS = normalInput.normalWS;
output.tangentWS = tangentWS;
output.viewDirTS = viewDirTS;
//Lightmap texture coordinates
OUTPUT_LIGHTMAP_UV(input.staticLightmapUV, unity_LightmapST, output.staticLightmapUV);
// Vertex spherical harmonic lighting
OUTPUT_SH(output.normalWS.xyz, output.vertexSH);
output.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
output.positionWS = vertexInput.positionWS;
output.shadowCoord = GetShadowCoord(vertexInput);
output.positionCS = vertexInput.positionCS;
(4) Fragment function
Part 1: Initialization data
half4 LitPassFragment(Varyings input) : SV_Target
{<!-- -->
// Get instance ID
    UNITY_SETUP_INSTANCE_ID(input);
    // for VR platform
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
    //SurfaceData is determined by material parameters
    SurfaceData surfaceData;
    InitializeStandardLitSurfaceData(input.uv, surfaceData);
//InputData is obtained from the information of the current vertex (normal map information needs to be passed in)
    InputData inputData;
    InitializeInputData(input, surfaceData.normalTS, inputData);
Part 2: Using this data to calculate surface shading

After obtaining the vertex information and surface material information, you can use this information for PBR shading.

 half4 color = UniversalFragmentPBR(inputData, surfaceData);
half4 UniversalFragmentPBR(InputData inputData, SurfaceData surfaceData)
{<!-- -->
    BRDFData brdfData;
    InitializeBRDFData(surfaceData, brdfData);
    // Clear-coat calculation...
    BRDFData brdfDataClearCoat = CreateClearCoatBRDFData(surfaceData, brdfData);
    half4 shadowMask = CalculateShadowMask(inputData);
    AmbientOcclusionFactor aoFactor = CreateAmbientOcclusionFactor(inputData, surfaceData);
    uint meshRenderingLayers = GetMeshRenderingLightLayer();
    // Get the main light source
    Light mainLight = GetMainLight(inputData, shadowMask, aoFactor);
    // Get the real-time lighting and lighting in the light map, and add it to mainLight
    MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI);
    
    LightingData lightingData = CreateLightingData(inputData, surfaceData);
// Get the global illumination Color
    lightingData.giColor = GlobalIllumination(brdfData, brdfDataClearCoat, surfaceData.clearCoatMask,
                                              inputData.bakedGI, aoFactor.indirectAmbientOcclusion, inputData.positionWS,
                                              inputData.normalWS, inputData.viewDirectionWS);

    if (IsMatchingLightLayer(mainLight.layerMask, meshRenderingLayers))
    {<!-- -->
        lightingData.mainLightColor = LightingPhysicallyBased(brdfData, brdfDataClearCoat,
                                                              mainLight,
                                                              inputData.normalWS, inputData.viewDirectionWS,
                                                              surfaceData.clearCoatMask, specularHighlightsOff);
    }
// extra light
    #if defined(_ADDITIONAL_LIGHTS)
uint pixelLightCount = GetAdditionalLightsCount();
\t
for (uint lightIndex = 0; lightIndex < min(_AdditionalLightsDirectionalCount, MAX_VISIBLE_LIGHTS); lightIndex + + )
{<!-- -->
Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
lightingData.additionalLightsColor + = LightingPhysicallyBased(brdfData, brdfDataClearCoat, light,
inputData.normalWS, inputData.viewDirectionWS,
surfaceData.clearCoatMask, specularHighlightsOff);
}
}
\t
LIGHT_LOOP_BEGIN(pixelLightCount)
Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
\t
if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
{<!-- -->
lightingData.additionalLightsColor + = LightingPhysicallyBased(brdfData, brdfDataClearCoat, light,
inputData.normalWS, inputData.viewDirectionWS,
surfaceData.clearCoatMask, specularHighlightsOff);
}
LIGHT_LOOP_END
    #endif

    return CalculateFinalColor(lightingData, surfaceData.alpha);
}
Part 3: Fog Effect
color.rgb = MixFog(color.rgb, inputData.fogCoord);

The Mixfog function is in ShaderVariablesFunctions.hlsl, passing in the fragment color value and fog factor.

half3 MixFog(half3 fragColor, half fogFactor)
{<!-- -->
    return MixFogColor(fragColor, unity_FogColor.rgb, fogFactor);
}

Add fog effect color value unity_FogColor.rgb.

half3 MixFogColor(half3 fragColor, half3 fogColor, half fogFactor)
{<!-- -->
    #if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
    //Determine the mixing value of the fog effect based on defined
        half fogIntensity = ComputeFogIntensity(fogFactor);
        // Mix color values
        fragColor = lerp(fogColor, fragColor, fogIntensity);
    #endif
    return fragColor;
}
Part 4: Whether to be transparent (“_Surface”)
color.a = OutputAlpha(color.a, _Surface);

Defined in ShaderVariablesFunctions.hlsl, the value of the final result color.a is determined based on whether surfaceType is transparent or opaque. (default is opaque)

half OutputAlpha(half outputAlpha, half surfaceType = half(0.0))
{<!-- -->
    return surfaceType == 1 ? outputAlpha : half(1.0);
}

Summary of function and macro definitions

  • TRANSFORM_TEX(tex,name): It calculates the uv of the model vertex and the two variables of Tiling and Offset to calculate the fixed-point uv for actual display.
    For example: #define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
  • float3 GetCameraPositionWS(); // Returns the world space camera position

Postscript

The code in this article is not entirely the source code of URP-LitShader, but some unnecessary parameter definitions and the code in macro definitions that are rarely used have been deleted. The purpose is to reduce reading complexity.