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

news2024/11/26 15:53:35

文章目录

  • 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

在这里插入图片描述

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的源代码,而是删除了一些不必要的参数定义,以及不太会用的宏定义内的代码。目的是降低阅读复杂度。

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

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

相关文章

excel中超级表和普通表的相互转换

1、普通表转换为超级表 选中表内任一单元格&#xff0c;然后按CtrlT&#xff0c;确认即可。 2、超级表转换为普通表 选中超级表内任一单元格&#xff0c;右键&#xff0c;表格&#xff0c;转换为区域&#xff0c;确定即可。 这时虽然已经变成了普通表&#xff0c;但样式没有…

案例 - 拖拽上传文件,生成缩略图

直接看效果 实现代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>拖拽上传文件</title>&l…

Node.js |(七)express案例实践:记账本 | 尚硅谷2023版Node.js零基础视频教程

文章目录 &#x1f4da;基本结构搭建&#x1f4da;响应静态网页&#x1f4da;获取表单数据&#x1f4da;借助lowdb保存账单信息&#x1f4da;完善成功提醒&#x1f4da;账单列表&#x1f4da;删除账单&#x1f4da;final 学习视频&#xff1a;尚硅谷2023版Node.js零基础视频教程…

DAIR-V2X-V 3D检测数据集 转为Kitti格式 | 可视化

本文分享在DAIR-V2X-V数据集中&#xff0c;将标签转为Kitti格式&#xff0c;并可视化3D检测效果。 一、将标签转为Kitti格式 DAIR-V2X包括不同类型的数据集&#xff1a; DAIR-V2X-IDAIR-V2X-VDAIR-V2X-CV2X-Seq-SPDV2X-Seq-TFDDAIR-V2X-C-Example: google_drive_linkV2X-Seq-…

关于最新版本Burp Suite可以在哪个基本类别中找到控制其更新行为的“更新”子类别

关于最新版本Burp Suite可以在哪个基本类别中找到控制其更新行为的“更新”子类别&#xff1f; In which base category can you find the "Updates" sub-category, which controls the Burp Suite update behaviour? 是Suite而不是Misc If your answer to this q…

IDEA重新choose source

大概现状是这样&#xff1a;之前有个工程&#xff0c;依赖了别的模块基础包&#xff0c;但当时并没有依赖包的源码工程&#xff0c;因此&#xff0c;通过鼠标左键点进去&#xff0c;看到的是jar包里的class文件&#xff0c;注释什么的都去掉了的&#xff0c;不好看。后面有这个…

qml添加滚动条

import QtQuick.Controls 2.15ScrollBar.vertical: ScrollBar {visible: flick1.contentHeight > flick1.heightanchors.right: parent.rightanchors.rightMargin: 40width: 10active: truecontentItem: Rectangle {radius: 6opacity: 0.5color: "#7882A0"} }

在字节跳动做了4年软件测试,9月无情被辞,细思极恐

​【文章末尾个大家留下了大量的福利】 某不知名 985 的本科&#xff0c;18年毕业加入字节&#xff0c;以“缩减成本”的名义无情被裁员&#xff0c;之后跳槽到了华为&#xff0c;一直从事软件测试的工作。之前没有实习经历&#xff0c;算是4年的工作经验吧。 这4年之间完成了…

大直径测径仪 一种高效且高精的大口径外径检测仪器

摘要 大直径测径仪是一种高效高精的大口径产品外径检测仪器&#xff0c;可适用于连续轧制无缝管材、皮尔格轧制无缝管材、直缝焊管、螺旋焊管等的在线检测。还可根据不同的产品规格调节测量范围。 引言 一些大口径的管材、棒材并不罕见&#xff0c;深埋地下的排水管道、输送管道…

企业级低代码开发,科技赋能让企业具备“驾驭软件的能力”

科技作为第一生产力&#xff0c;其强大的影响力在各个领域中都有所体现。数字技术&#xff0c;作为科技领域中的一股重要力量&#xff0c;正在对传统的商业模式进行深度的变革&#xff0c;为各行业注入新的生命力。随着数字技术的不断发展和应用&#xff0c;企业数字化转型的趋…

为什么电力公司很少用轨道式的电表?

在日常生活中&#xff0c;电表作为电力系统的重要组成部分&#xff0c;承担着电能计量、结算等职能。然而&#xff0c;相较于其他类型的电表&#xff0c;电力公司为何很少采用轨道式的电表呢&#xff1f;本文将带您走进电表的世界&#xff0c;揭秘电表发展历程与技术优劣势&…

【独家揭秘】跨境电商源码独立开发,软著认证,前后端全开源,无加密,交付源码,商用无忧!

在这个数字化快速发展的时代&#xff0c;跨境电商已成为全球商业的重要趋势。为了帮助您快速进入这个潜力巨大的市场&#xff0c;我们独家推出了一款经过全面验证的跨境电商源码解决方案!这款源码具有独立开发、软著认证、前后端全开源、无加密等特点&#xff0c;为您的商业运营…

企业微信vs个人微信:对比对照一览表

继微信后&#xff0c;腾讯推出了企业微信。企业微信可以添个人微信为好友&#xff0c;有群聊和朋友圈&#xff0c;粗看起来与个人微信十分相似&#xff0c;那么它们有什么区别呢&#xff1f; 企业微信和个人微信的区别是什么&#xff0c;咱今天两张图来对比看看~

【会话技术】Cookie和Session的工作流程和区别

Cookie技术 web程序是通过HTTP协议传输的&#xff0c;而HTTP是无状态的&#xff0c;即后续如果还要使用前面已经传输的数据&#xff0c;就还需要重传。这样如果数据量很大的情况下&#xff0c;效率就会大打折扣。Cookie的出现就是为了解决这个问题。 Cookie的工作流程&#x…

TDD、BDD、ATDD以及SBE的概念和区别

在软件开发或是软件测试中会遇到以下这些词&#xff1a;TDD 、BDD 、ATDD以及SBE&#xff0c;这些词代表什么意思呢&#xff1f; 它们之间有什么关系吗&#xff1f; TDD 、BDD 、ATDD以及SBE的基本概念 TDD&#xff1a;&#xff08;Test Driven Development&#xff09;是一种…

Linux中固定ip端口和修改ip地址

一&#xff0c;更改虚拟网络编辑器 1&#xff0c;首先启动VMware&#xff0c;选择自己要更改ip或固定ip的虚拟机&#xff0c;并找到虚拟网络配编辑器&#xff0c;点击进入 2&#xff0c;进入之后需要点击右下角获取管理员权限后才能修改&#xff0c;有管理员权限之后图片如下 …

影响金融软件开发价格的因素有哪些?

随着科技的发展&#xff0c;金融行业逐渐向数字化和信息化转型&#xff0c;在这个过程中&#xff0c;金融软件开发成为了重要的支撑&#xff0c;然而&#xff0c;金融软件开发的价格是一个复杂的问题&#xff0c;受到多种因素的影响&#xff0c;本文将详细解析影响金融软件开发…

HiSilicon352 android9.0 适配红外遥控器

海思Android解决方案在原生Android基础上&#xff0c;基于传统电视用户使用习惯&#xff0c;增加了对红外遥控器和按键板的支持&#xff0c;使传统电视用户能更好适应智能电视方案。 一.功能描述&#xff1a; 在系统启动时&#xff0c;会先启动android_ir_user&#xff1b;vinp…

程序员可以做哪些副业?我整理的千字副业指南。

都说不想做副业的程序员不是好程序员&#xff0c;尤其是在经济形势不好的现在&#xff0c;有一份靠谱和稳定的副业更是成为了程序员的不二之选。程序员的副业是细水长流型的&#xff0c;虽然收入未必能超过主业&#xff0c;但胜在每月稳定入账&#xff0c;可以作为小金库和备用…

基于STC12C5A60S2系列1T 8051单片机SPI通信应用

基于STC12C5A60S2系列1T 8051单片机SPI通信应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍STC12C5A60S2系列1T 8051单片机SPI通信介绍STC12C5A60S2系列1T 8051单片…