虽然都快2020了,但是项目用的是2018版本,最近要改下材质,所以分析一下18版的HDRP Standard。
暂时不考虑多层材质和曲面细分,并且项目用的是Forward管线,也暂时不分析Deffered。
先简单看看shader中直接引用的库。
开头介绍了一些library编写的惯例:
uniform float4 packedArray[3];
static float unpackedArray[12] = (float[12])packedArray;
然后是一些跨平台的工作。
最后定义了一些常用函数,有一点类似原UnityCG的功能。
风相关的属性和函数。
申明了varying/interpolator的结构体。附带Debug代码。
定义每种Pass为0 - n,是自动生成的。
定义属性。
定义了HDRP的属性。附带一些相关函数。
光照、阴影、采样、区域光及IBL。
AlphaBlend相关。
主要和间接光和Cluster及Tile相关。
standard主体。
光照。
一些宏的定义。
一些宏的定义。获取UV及GetSurfaceAndBuiltinData方法。
定义Vert和Frag。
在简单的了解之后,从最后ShaderPassForward中给我们的Vert和Frag来切入,来了解forword pass的整个流程。
PackedVaryingsType Vert(AttributesMesh inputMesh)
{
VaryingsType varyingsType;
varyingsType.vmesh = VertMesh(inputMesh);
return PackVaryingsType(varyingsType);
}
把顶点的信息用VertMesh函数计算后储存至varyingsType.vmesh,再打包成PackedVaryingsType类型。
结构体和函数都在VertMesh.hlsl及VaryingMesh.hlsl中定义。
先看这几个结构体。
AttributesMesh
struct AttributesMesh
{
float3 positionOS : POSITION;
#ifdef ATTRIBUTES_NEED_NORMAL
float3 normalOS : NORMAL;
#endif
#ifdef ATTRIBUTES_NEED_TANGENT
float4 tangentOS : TANGENT; // Store sign in w
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD0
float2 uv0 : TEXCOORD0;
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD1
float2 uv1 : TEXCOORD1;
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD2
float2 uv2 : TEXCOORD2;
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD3
float2 uv3 : TEXCOORD3;
#endif
#ifdef ATTRIBUTES_NEED_COLOR
float4 color : COLOR;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
VaryingsType
#define VaryingsType VaryingsToPS
如果不是曲面细分,则为VaryingsToPS。
struct VaryingsToPS
{
VaryingsMeshToPS vmesh;
#ifdef VARYINGS_NEED_PASS
VaryingsPassToPS vpass;
#endif
};
其中VARYINGS_NEED_PASS只有在计算Motion的pass中会定义。
struct VaryingsMeshToPS
{
float4 positionCS;
#ifdef VARYINGS_NEED_POSITION_WS
float3 positionRWS;
#endif
#ifdef VARYINGS_NEED_TANGENT_TO_WORLD
float3 normalWS;
float4 tangentWS; // w contain mirror sign
#endif
#ifdef VARYINGS_NEED_TEXCOORD0
float2 texCoord0;
#endif
#ifdef VARYINGS_NEED_TEXCOORD1
float2 texCoord1;
#endif
#ifdef VARYINGS_NEED_TEXCOORD2
float2 texCoord2;
#endif
#ifdef VARYINGS_NEED_TEXCOORD3
float2 texCoord3;
#endif
#ifdef VARYINGS_NEED_COLOR
float4 color;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
PackedVaryingsType
#define PackedVaryingsType PackedVaryingsToPS
如果不是曲面细分,则为PackedVaryingsToPS。
struct PackedVaryingsToPS
{
#ifdef VARYINGS_NEED_PASS
PackedVaryingsPassToPS vpass;
#endif
PackedVaryingsMeshToPS vmesh;
};
struct PackedVaryingsMeshToPS
{
float4 positionCS : SV_Position;
#ifdef VARYINGS_NEED_POSITION_WS
float3 interpolators0 : TEXCOORD0;
#endif
#ifdef VARYINGS_NEED_TANGENT_TO_WORLD
float3 interpolators1 : TEXCOORD1;
float4 interpolators2 : TEXCOORD2;
#endif
// Allocate only necessary space if shader compiler in the future are able to automatically pack
#ifdef VARYINGS_NEED_TEXCOORD1
float4 interpolators3 : TEXCOORD3;
#elif defined(VARYINGS_NEED_TEXCOORD0)
float2 interpolators3 : TEXCOORD3;
#endif
#ifdef VARYINGS_NEED_TEXCOORD3
float4 interpolators4 : TEXCOORD4;
#elif defined(VARYINGS_NEED_TEXCOORD2)
float2 interpolators4 : TEXCOORD4;
#endif
#ifdef VARYINGS_NEED_COLOR
float4 interpolators5 : TEXCOORD5;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID // Must be declare before FRONT_FACE_SEMANTIC
#if defined(VARYINGS_NEED_CULLFACE) && SHADER_STAGE_FRAGMENT
FRONT_FACE_TYPE cullFace : FRONT_FACE_SEMANTIC;
#endif
};
再看这两个函数
VertMesh
VaryingsMeshType VertMesh(AttributesMesh input)
{
VaryingsMeshType output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
#if defined(HAVE_MESH_MODIFICATION)
input = ApplyMeshModification(input);
#endif
// This return the camera relative position (if enable)
float3 positionRWS = TransformObjectToWorld(input.positionOS);
#ifdef ATTRIBUTES_NEED_NORMAL
float3 normalWS = TransformObjectToWorldNormal(input.normalOS);
#else
float3 normalWS = float3(0.0, 0.0, 0.0); // We need this case to be able to compile ApplyVertexModification that doesn't use normal.
#endif
#ifdef ATTRIBUTES_NEED_TANGENT
float4 tangentWS = float4(TransformObjectToWorldDir(input.tangentOS.xyz), input.tangentOS.w);
#endif
// Do vertex modification in camera relative space (if enable)
#if defined(HAVE_VERTEX_MODIFICATION)
ApplyVertexModification(input, normalWS, positionRWS, _Time);
#endif
#ifdef TESSELLATION_ON
output.positionRWS = positionRWS;
output.normalWS = normalWS;
#if defined(VARYINGS_NEED_TANGENT_TO_WORLD) || defined(VARYINGS_DS_NEED_TANGENT)
output.tangentWS = tangentWS;
#endif
#else
#ifdef VARYINGS_NEED_POSITION_WS
output.positionRWS = positionRWS;
#endif
output.positionCS = TransformWorldToHClip(positionRWS);
#ifdef VARYINGS_NEED_TANGENT_TO_WORLD
output.normalWS = normalWS;
output.tangentWS = tangentWS;
#endif
#endif
#if defined(VARYINGS_NEED_TEXCOORD0) || defined(VARYINGS_DS_NEED_TEXCOORD0)
output.texCoord0 = input.uv0;
#endif
#if defined(VARYINGS_NEED_TEXCOORD1) || defined(VARYINGS_DS_NEED_TEXCOORD1)
output.texCoord1 = input.uv1;
#endif
#if defined(VARYINGS_NEED_TEXCOORD2) || defined(VARYINGS_DS_NEED_TEXCOORD2)
output.texCoord2 = input.uv2;
#endif
#if defined(VARYINGS_NEED_TEXCOORD3) || defined(VARYINGS_DS_NEED_TEXCOORD3)
output.texCoord3 = input.uv3;
#endif
#if defined(VARYINGS_NEED_COLOR) || defined(VARYINGS_DS_NEED_COLOR)
output.color = input.color;
#endif
return output;
}
前两个宏是Instance相关的操作,定义在UnityInstancing.hlsl中。
ApplyMeshModification和地形相关,这里就不分析了。
矩阵计算都在SpaceTransforms.hlsl中定义,可以去那里详细查看。
PackVaryingsToPS
PackedVaryingsToPS PackVaryingsToPS(VaryingsToPS input)
{
PackedVaryingsToPS output;
output.vmesh = PackVaryingsMeshToPS(input.vmesh);
#ifdef VARYINGS_NEED_PASS
output.vpass = PackVaryingsPassToPS(input.vpass);
#endif
return output;
}
PackedVaryingsMeshToPS PackVaryingsMeshToPS(VaryingsMeshToPS input)
{
PackedVaryingsMeshToPS output;
UNITY_TRANSFER_INSTANCE_ID(input, output);
output.positionCS = input.positionCS;
#ifdef VARYINGS_NEED_POSITION_WS
output.interpolators0 = input.positionRWS;
#endif
#ifdef VARYINGS_NEED_TANGENT_TO_WORLD
output.interpolators1 = input.normalWS;
output.interpolators2 = input.tangentWS;
#endif
#ifdef VARYINGS_NEED_TEXCOORD0
output.interpolators3.xy = input.texCoord0;
#endif
#ifdef VARYINGS_NEED_TEXCOORD1
output.interpolators3.zw = input.texCoord1;
#endif
#ifdef VARYINGS_NEED_TEXCOORD2
output.interpolators4.xy = input.texCoord2;
#endif
#ifdef VARYINGS_NEED_TEXCOORD3
output.interpolators4.zw = input.texCoord3;
#endif
#ifdef VARYINGS_NEED_COLOR
output.interpolators5 = input.color;
#endif
return output;
}
下篇再继续分析Frag。