URP内置Lit.Shader文件ForwardLit Pass解析

文章目录

  • Lit 主文件
    • Properties
    • SubShader代码块
      • FormardLit
        • 标签
        • 编译命令
        • 声明关键字
          • 材质属性关键字 Material Keywords
          • 渲染流水线关键词 Universal Pipeline keywords
          • Unity定义的关键词 Unity defined keywords
        • 包含指令
      • 1. LitInput.hlsl
        • (1)属性变量
        • (2)纹理采样函数
        • (3)AO采样函数
        • (4)表面数据初始化函数
          • SurfaceData:片元数据,在`SurfaceData.hlsl`中
          • SurfaceInput: 获取SurfaceData的函数,在`SurfaceInput.hlsl`中
        • (4)表面数据初始化函数
      • 2. LitForwardPass.hlsl
        • (1)片元函数输入结构体
        • 引用库:Common.hlsl,通用库(包括:规范,real定义,通用函数)
          • 常用函数
        • 引用库:Input.hlsl
          • InputData结构体
          • Constant Buffers
          • 变换矩阵的宏
        • (2)输入数据初始化函数
        • 引用库:SpaceTransform.hlsl
        • (3)顶点函数
          • 第一部分:初始化部分
          • 第二部分:初始化结构体以供调用
            • 补充:Core.hlsl
            • 补充:ShaderVariablesFunctions.hlsl
          • 第三部分:得到计算相关数据
        • (4)片段函数
          • 第一部分:初始化数据
          • 第二部分:使用这些数据计算表面着色
          • 第三部分:雾效
          • 第四部分:是否透明("_Surface")
  • 函数和宏定义总结
  • 后记

Lit 主文件

Properties

[MainTexture]主纹理,可以使用Material.mainTexture访问
[MainColor]主颜色,可以使用Material.color访问
[ToggleOff] 使数值类型的属性在材质面板上显示为开关样式,并在编译指令中可声明关键字(大写属性名称+OFF
[Toggle]使数值类型的属性在材质面板上显示为开关样式,并在编译指令中可声明关键字(大写属性名称+ON

SubShader代码块

只有标注了如下标签的SubShader,才能在URP中运行

 "RenderPipeline" = "UniversalPipeline" 

SubShader一共含有5个标签:

  • FormardLit

FormardLit

标签

Tags{"LightMode" = "UniversalForward"}

编译命令

不为 gles gles3 glcore功能级别的渲染平台编译Shader,使用4.5版本

#pragma exclude_renderers gles gles3 glcore
#pragma target 4.5
声明关键字

关键字分为三类:

  • 材质属性关键字 Material Keywords
  • 渲染流水线关键词 Universal Pipeline keywords
  • Unity定义的关键词 Unity defined keywords
材质属性关键字 Material Keywords
// -------------------------------------
// Material Keywords
#pragma shader_feature_local _NORMALMAP					// 添加了法线贴图时,传入关键字
#pragma shader_feature_local _PARALLAXMAP				// 视差图
#pragma shader_feature_local _RECEIVE_SHADOWS_OFF		// 当关闭接受阴影
#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED	//		????????
#pragma shader_feature_local_fragment _SURFACE_TYPE_TRANSPARENT	//表面类型透明    ?????
#pragma shader_feature_local_fragment _ALPHATEST_ON			// 开启透明裁剪时~
#pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON	// 混合模式为Premultiply
#pragma shader_feature_local_fragment _EMISSION				// 开启自发光
#pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP	// 金属(metallic)工作流使用金属贴图、或高光工作流使用高光贴图
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A	// 当光滑度数据选择了Specular Alpha
#pragma shader_feature_local_fragment _OCCLUSIONMAP							// 当添加了AO贴图
#pragma shader_feature_local_fragment _SPECULARHIGHLIGHTS_OFF				// 当关闭了镜面高光反射
#pragma shader_feature_local_fragment _ENVIRONMENTREFLECTIONS_OFF			// 当关闭了环境反射
#pragma shader_feature_local_fragment _SPECULAR_SETUP						// 当选择了高光工作流
渲染流水线关键词 Universal Pipeline keywords

作为整体流水线的设置
在RenderPipelineAsset资源下设置即可

// -------------------------------------
// Universal Pipeline keywords
					// 无阴影、阴影、级联阴影、屏幕空间阴影
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN	
					// 无额外光照、额外顶点光照、额外片元光照
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
					// 无额外灯光阴影、开启额外灯光阴影
#pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
					// 光照探针混合
#pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING
					// 方框投影反射探针
#pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION
					// 软阴影
#pragma multi_compile_fragment _ _SHADOWS_SOFT
					// SSAO
#pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
					// 其他的一些奇奇怪怪的参数
#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

URP内置Lit.Shader文件ForwardLit Pass解析_第1张图片

Unity定义的关键词 Unity defined keywords

这一部分的关键字与场景光照有关,在Lighting设置面板中

// -------------------------------------
// Unity defined keywords
#pragma multi_compile _ LIGHTMAP_SHADOW_MIXING  // 光照贴图阴影混合
#pragma multi_compile _ SHADOWS_SHADOWMASK		//
#pragma multi_compile _ DIRLIGHTMAP_COMBINED	//是否使用Directional模式光照烘培
#pragma multi_compile _ LIGHTMAP_ON				//是否启用光照贴图
#pragma multi_compile _ DYNAMICLIGHTMAP_ON		//是否启用动态光照贴图
#pragma multi_compile_fog						//是否启用雾效
#pragma multi_compile_fragment _ DEBUG_DISPLAY	//
包含指令
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing	// 使Shader支持GPU实例
#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 "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)属性变量

常量缓冲区

CBUFFER_START(UnityPerMaterial)
	... 可在Shader中使用
CBUFFER_END

纹理

TEXTURE2D(_ParallaxMap);        SAMPLER(sampler_ParallaxMap);

SAMPLER可以有其他使用方法

  • SAMPLER(filter_wrap)
  • SAMPLER(filter_wrapU_wrapV)
    • filter:point、linear、triLinear
    • wrap:clamp、repeat、mirror、mirrorOnce
(2)纹理采样函数

对金属度或高光度进行采样得到 half4 specGloss 返回

half4 SampleMetallicSpecGloss(float2 uv, half albedoAlpha)
(3)AO采样函数

返回AO贴图的采样结果

half SampleOcclusion(float2 uv)
(4)表面数据初始化函数
inline void InitializeStandardLitSurfaceData(float2 uv, out SurfaceData outSurfaceData)

表面数据初始化函数需要用到SurfaceData

SurfaceData:片元数据,在SurfaceData.hlsl
struct SurfaceData
{
    half3 albedo;				//颜色(反照率)
    half3 specular;             //高光反射
    half  metallic;				//金属度
    half  smoothness;			//光滑度
    half3 normalTS;				//法线 TS (瓷砖式显示Tiling,偏移Offset)
    half3 emission;				//自发光
    half  occlusion;			//遮蔽值
    half  alpha;				//透明度
    half  clearCoatMask;		//透明层Mask
    half  clearCoatSmoothness;	//--------
};
SurfaceInput: 获取SurfaceData的函数,在SurfaceInput.hlsl

包含库:

#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"

纹理:

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

函数:
透明度函数: 获取透明属性,并根据_ALPHATEST_ON宏,决定是否开启剔除,并剔除。

//  参数:   Albedo纹理(BaseMap)的Alpha通道,基础色(BaseColor),裁剪值
half Alpha(half albedoAlpha, half4 color, half cutoff)

Albedo纹理采样函数

//                 纹理坐标                纹理变量                采样器
half4 SampleAlbedoAlpha(float2 uv, TEXTURE2D_PARAM(albedoAlphaMap, sampler_albedoAlphaMap))
{
    return half4(SAMPLE_TEXTURE2D(albedoAlphaMap, sampler_albedoAlphaMap, uv));
}

法线贴图采样函数

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

自发光贴图采样函数

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

现在我们回到表面数据初始化函数

(4)表面数据初始化函数

初始化SurfaceData结构体中的变量,并将其输出。

inline void InitializeStandardLitSurfaceData(float2 uv, out SurfaceData outSurfaceData)
{
	// 得到纹理alpha值
    half4 albedoAlpha = SampleAlbedoAlpha(uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap));
    // 混合系数alpha值,并剔除
    outSurfaceData.alpha = Alpha(albedoAlpha.a, _BaseColor, _Cutoff);

	// 采样高光或金属值
    half4 specGloss = SampleMetallicSpecGloss(uv, albedoAlpha.a);
    // 保存颜色值
    outSurfaceData.albedo = albedoAlpha.rgb * _BaseColor.rgb;

	// 保存高光值、或金属值
#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
	// 光滑度
    outSurfaceData.smoothness = specGloss.a;
    // 法线
    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)片元函数输入结构体
struct Varyings
{
	// 直接参数
    float2 uv                       : TEXCOORD0;
	float3 normalWS                 : TEXCOORD2;
		// 光照贴图的纹理坐标:float2 lmName : TEXCOORD##index
		// 或球谐函数的纹理坐标?:half3 shName : TEXCOORD##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
};
引用库:Common.hlsl,通用库(包括:规范,real定义,通用函数)
常用函数
real DegToRad(real deg)//角度转弧度
real RadToDeg(real rad)//弧度转角度
float Length2(float3 v)//返回向量长度的平方
real3 SafeNormalize(float3 inVec)//返回标准化的3维向量
real SafeDiv(real numer, real denom)//返回numer/denom

引用库:Input.hlsl
InputData结构体
struct InputData
{
    float3  positionWS;
    float4  positionCS;
    float3  normalWS;
    half3   viewDirectionWS;
    float4  shadowCoord;	//在阴影贴图中的UV
    half    fogCoord;		//雾的等级
    half3   vertexLighting;	//顶点光照(Additional Light)
    half3   bakedGI;		//全局光照(光照贴图或球谐函数计算)
    float2  normalizedScreenSpaceUV;
    half4   shadowMask;
    half3x3 tangentToWorld;	//法线变换到世界空间的TBN矩阵,与model矩阵有关
    #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

部分其他变量定义

half4 _GlossyEnvironmentColor;// 环境反射颜色
half4 _SubtractiveShadowColor;// 阴影颜色
half4 _GlossyEnvironmentCubeMap_HDR;
TEXTURECUBE(_GlossyEnvironmentCubeMap);
SAMPLER(sampler_GlossyEnvironmentCubeMap);
#define _InvCameraViewProj unity_MatrixInvVP
float4 _ScaledScreenParams;
float4 _MainLightPosition;	// 主光源位置
half4 _MainLightColor;		// 主光源颜色
half4 _MainLightOcclusionProbes;	// 主光源遮蔽球鞋探针???
uint _MainLightLayerMask;			// 主光源层遮罩
half4 _AmbientOcclusionParam;
half4 _AdditionalLightsCount;
变换矩阵的宏
#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)输入数据初始化函数

初始化InputData结构体,函数需要传入Varyings结构体和切线空间法线,然后输出InputData结构体。

void InitializeInputData(Varyings input, half3 normalTS, out InputData inputData)
	inputData = (InputData)0;// 初始化 (该写法为语法结构)
引用库:SpaceTransform.hlsl

包含了所有与空间变换相关的函数

(3)顶点函数
第一部分:初始化部分
Varyings output = (Varyings)0;

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

初始化输出结构体。
使顶点着色器可以获取到GPU实例的ID
将实例ID传递给输出结构体
针对VR平台进行的顶点操作(VR平台由两个摄像机生成)

第二部分:初始化结构体以供调用

声明了两个结构体,并将其初始化。
这两个结构体在Core.hlsl中定义,初始化函数在ShaderVariablesFunctions.hlsl中定义,目的是传入一个所需的变量,得到与其相关的所有变量,方便用户在编写代码时可以直接调用。

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);
补充: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;	// 世界空间切线
    real3 bitangentWS;	// 世界空间次切线
    float3 normalWS;	// 世界空间法线
};
补充:ShaderVariablesFunctions.hlsl
VertexPositionInputs GetVertexPositionInputs(float3 positionOS)
VertexNormalInputs GetVertexNormalInputs(float3 normalOS)//只填充normalWS
VertexNormalInputs GetVertexNormalInputs(float3 normalOS, float4 tangentOS)//填充三个切线
...
第三部分:得到计算相关数据

计算数据:

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:额外灯光光照值,由多个灯光(距离衰减、夹角衰减后)累加获得。VertexLighting()函数在Lighting.hlsl中定义。
  • fogFactor :雾效因子,越远越大,ComputeFogFactor()函数在ShaderVariablesFunctions.hlsl文件中定义,函数需要传入深度值Z。

保存数据:

output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);//TRANSFORM_TEX==> scale && offset
output.normalWS = normalInput.normalWS;
output.tangentWS = tangentWS;
output.viewDirTS = viewDirTS;
// 光照贴图纹理坐标
OUTPUT_LIGHTMAP_UV(input.staticLightmapUV, unity_LightmapST, output.staticLightmapUV);
// 顶点球谐函数光照
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)片段函数
第一部分:初始化数据
half4 LitPassFragment(Varyings input) : SV_Target
{
	// 获取实例ID
    UNITY_SETUP_INSTANCE_ID(input);
    // 用于VR平台
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
    //SurfaceData由材质参数决定
    SurfaceData surfaceData;
    InitializeStandardLitSurfaceData(input.uv, surfaceData);
	//InputData由当前顶点的信息得到(需要传入法线贴图信息)
    InputData inputData;
    InitializeInputData(input, surfaceData.normalTS, inputData);
第二部分:使用这些数据计算表面着色

得到顶点信息和表面材质信息,就可以将这些信息用于PBR着色。

	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();
    // 得到主光源
    Light mainLight = GetMainLight(inputData, shadowMask, aoFactor);
    // 得到实时光照和光照贴图中的光照,并加到mainLight中
    MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI);
    
    LightingData lightingData = CreateLightingData(inputData, surfaceData);
	// 得到全局光照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);
    }
	// 额外光照
    #if defined(_ADDITIONAL_LIGHTS)
	    uint pixelLightCount = GetAdditionalLightsCount();
	
	    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);
	        }
	    }
	
	    LIGHT_LOOP_BEGIN(pixelLightCount)
	        Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
	
	        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);
}
第三部分:雾效
color.rgb = MixFog(color.rgb, inputData.fogCoord);

Mixfog函数在ShaderVariablesFunctions.hlsl中,传入 片元颜色值 和 雾效因子

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

加入雾效颜色值unity_FogColor.rgb

half3 MixFogColor(half3 fragColor, half3 fogColor, half fogFactor)
{
    #if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
    	// 根据 defined 决定雾效的混合值
        half fogIntensity = ComputeFogIntensity(fogFactor);
        // 混合颜色值
        fragColor = lerp(fogColor, fragColor, fogIntensity);
    #endif
    return fragColor;
}
第四部分:是否透明(“_Surface”)
color.a = OutputAlpha(color.a, _Surface);

定义在ShaderVariablesFunctions.hlsl中,根据surfaceType是透明还是不透明决定最终结果color.a的值。(默认为不透明)

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

函数和宏定义总结

  • TRANSFORM_TEX(tex,name):就是将模型顶点的uv和Tiling、Offset两个变量进行运算,计算出实际显示用的定点uv。
    如:#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
  • float3 GetCameraPositionWS(); // 返回世界空间摄像机位置

后记

该文章中代码并不完全是URP–LitShader的源代码,而是删除了一些不必要的参数定义,以及不太会用的宏定义内的代码。目的是降低阅读复杂度。

你可能感兴趣的:(Unity,unity,URP,Lit.Shader)