赞
踩
本篇开始分析simple lit shader。我们通过分析unlit shader了解了URP shader的结构,以及一些基础功能。而simple lit shader包含了更多的内容。本篇开始,就不会特别仔细的逐行去分析shader文件了,只会针对pass的功能中比较有意思且之前没看到过的内容进行分析。
名字为ForwardLit
的pass,它的Tags为:
Tags { "LightMode" = "UniversalForward" }
根据URP的文档:
UniversalForward : The Pass renders object geometry and evaluates all light contributions. URP uses this tag value in the Forward Rendering Path.
说明这是一个前向渲染路径的pass,虽然URP(至少是10.8.1版本)还没有正式支持Deferred Rendering,但URP已经为它打了很多基础,所以会特意标明这个pass是前向渲染还是延迟渲染,如果是延迟渲染则会使用LightModeUniversalGBuffer
,SimpleLit shader也有这个pass,但是暂时不会研究它。
看一下ForwardLit支持的关键字,就可以大概看出实现了哪些功能,当然本身的功能就是光照不必说。
// ------------------------------------- // Material Keywords #pragma shader_feature_local_fragment _ALPHATEST_ON #pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON #pragma shader_feature_local_fragment _ _SPECGLOSSMAP _SPECULAR_COLOR #pragma shader_feature_local_fragment _GLOSSINESS_FROM_BASE_ALPHA #pragma shader_feature_local _NORMALMAP #pragma shader_feature_local_fragment _EMISSION #pragma shader_feature_local _RECEIVE_SHADOWS_OFF // ------------------------------------- // Universal Pipeline keywords #pragma multi_compile _ _MAIN_LIGHT_SHADOWS #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS #pragma multi_compile_fragment _ _SHADOWS_SOFT #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING #pragma multi_compile _ SHADOWS_SHADOWMASK #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION // ------------------------------------- // Unity defined keywords #pragma multi_compile _ DIRLIGHTMAP_COMBINED #pragma multi_compile _ LIGHTMAP_ON #pragma multi_compile_fog //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #pragma multi_compile _ DOTS_INSTANCING_ON
可以看到,这些关键字分了几类。比如Material Keywords
都是使用shader feature定义的,这些是材质上可以开关选择的关键字,比如我们之前看到过的alpha test, alpha premultiply;而simpeLit增加的有Specular GlossMap/Specular Color, Normalmap, Emission以及ReceiveShadowsOff,除了最后一个,都是和计算光照相关的选项,涉及到高光,法线贴图和自发光,我们会在shader里面看到它们的实现。
而Universal Pipeline keywords
这一组则是URP的一些全局设置相关的,这里的全局只是相对于材质来说,也不是local/global keywords那个全局。比如_MAIN_LIGHT_SHADOWS
决定了是否使用主光阴影,_MAIN_LIGHT_SHADOWS_CASCADE
是是否主光阴影使用级联阴影。Additional Lights相关的关键字是控制附加灯相关的光照和阴影。Lightmap shadow mixing和shadow mask是Unity的混合光照相关。
Unity defined keywords
这一组顾名思义就是Unity定义的关键字了,比如lightmap开关和深度雾。
此外还有GPU Instancing
这组。
#include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitForwardPass.hlsl"
这也是URP的惯例了,一个Pass自身的hlsl代码分为Input和Pass两部分。
在分析unlit shader时,我没有太关注unlit input,但是这次我打算详细的分析一下了。
SimpleLit input hlsl包含了shader使用的uniform的定义,uniform可能是以CBuffer的形式定义,也可能是shader全局变量的形式。使用CBUffer形式的往往是为了兼容SRPBatcher或者Instancing,打包进CBuffer的uniform往往是要经常变化的,比如随材质变化或者随instance变化;而全局变量的uniform就是全局改变的。
有几个内容需要关注:
这个文件就是SimpleLit前向渲染pass的主要代码了。首先它一开始就引用了"Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
文件,这个文件非常重要,值得好好研读。这里面几乎包含了URP光照相关的全部shader库了,在相关shader引用到里面的内容时会做说明。回到SimpleLit,定义了如下的顶点属性:
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float4 tangentOS : TANGENT;
float2 texcoord : TEXCOORD0;
float2 lightmapUV : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
坐标,法线,切线,两套uv,基本全了,毕竟要算光照都不能少,除了没用顶点色。再看VS的输出以及FS的输入:
struct Varyings { float2 uv : TEXCOORD0; DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 1); float3 posWS : TEXCOORD2; // xyz: posWS #ifdef _NORMALMAP float4 normal : TEXCOORD3; // xyz: normal, w: viewDir.x float4 tangent : TEXCOORD4; // xyz: tangent, w: viewDir.y float4 bitangent : TEXCOORD5; // xyz: bitangent, w: viewDir.z #else float3 normal : TEXCOORD3; float3 viewDir : TEXCOORD4; #endif half4 fogFactorAndVertexLight : TEXCOORD6; // x: fogFactor, yzw: vertex light #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) float4 shadowCoord : TEXCOORD7; #endif float4 positionCS : SV_POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO };
VS输出啥其实是看FS的计算需要啥,首先uv, 世界坐标,法线,视线方向等计算Blinn-Phong模型光照所需的经典角色一个不少;如果启用了法线贴图,还需要输出切线坐标系;另外似乎还有所谓的vertex light;当然clip sapce postition是必须的。
由于篇幅所限,本篇只是起了个头,结果挖了好几个坑。至少我们现在对SimpeLit的功能有了大体的了解,光照部分应该是使用了Blinn-Phong模型,支持法线贴图。下篇将继续分析前向渲染路径的光照。之后会有几篇介绍SRP Batcher和Instancing。然后是Shadow Caster等等。基本上一个SimpleLit就可以挖出很多东西了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。