A闪的 BLOG 技术与人文
定义采样纹理的采样器状态。应当与采样节点(如 Sample Texture 2D 节点)结合使用。可以使用下拉选单参数 Filter 设置过滤器模式,并使用下拉选单参数 Wrap 设置包裹模式。
使用单个 Sample State 节点时,可使用不同的采样器参数对 2D 纹理进行两次采样,无需对 2D 纹理本身进行两次定义。
有些过滤和包裹模式仅在特定平台上可用。
SamplerState _SamplerState_Out = _SamplerState_Linear_Repeat_sampler;
定义要在着色器中使用的常量 2D 纹理数组资源。要对 2D 纹理数组资源采样,必须将其与 Sample Texture 2D Array 节点结合使用。使用单个 Texture 2D Array Asset 节点时,可使用不同的参数对 2D 纹理数组进行两次采样,无需对 2D 纹理数组本身进行两次定义。
TEXTURE2D_ARRAY(_Texture2DArrayAsset);
SAMPLER(sampler_Texture2DArrayAsset);
定义要在着色器中使用的常量 2D 纹理资源。要对 2D 纹理资源采样,必须将其与 Sample Texture 2D 节点结合使用。使用单个 Texture 2D Asset 节点时,可使用不同的参数对 2D 纹理进行两次采样,无需对 2D 纹理本身进行两次定义。
TEXTURE2D(_Texture2DAsset);
SAMPLER(sampler_Texture2DAsset);
定义要在着色器中使用的常量 3D 纹理资源。要对 3D 纹理资源采样,必须将其与 Sample Texture 3D 节点结合使用。使用单个 Texture 3D Asset 节点时,可使用不同的参数对 3D 纹理进行两次采样,无需对 3D 纹理本身进行两次定义。
TEXTURE3D(_Texture3DAsset);
SAMPLER(sampler_Texture3DAsset);
返回输入 In 的绝对值。输入动态矢量的正数分量将保持正数,负数分量将被反转并变为正数。
void Unity_Absolute_float4(float4 In, out float4 Out)
{
Out = abs(In);
}
返回输入 In 的幂值。可以使用节点上的 Base 下拉选单在 base-e 和 base-2 之间切换底数。
Base E
void Unity_Exponential_float4(float4 In, out float4 Out)
{
Out = exp(In);
}
Base 2
void Unity_Exponential2_float4(float4 In, out float4 Out)
{
Out = exp2(In);
}
返回输入 In 的长度。这也称为大小 (magnitude)。矢量的长度是使用毕达哥拉斯定理 (Pythagorean Theorum) 计算的。
void Unity_Length_float4(float4 In, out float Out)
{
Out = length(In);
}
返回输入 In 的对数。Log 是 Exponential 节点的逆运算。
例如,输入值为 3 时,base-2 Exponential 的结果是 8。
因此,输入值为 8 时,base-2 Log 的结果是 3。
可以使用节点上的 Base 下拉选单在 base-e、base-2 和 base-10 之间切换底数。
Base E
void Unity_Log_float4(float4 In, out float4 Out)
{
Out = log(In);
}
Base 2
void Unity_Log2_float4(float4 In, out float4 Out)
{
Out = log2(In);
}
Base 10
void Unity_Log10_float4(float4 In, out float4 Out)
{
Out = log10(In);
}
返回输入 A 除以输入 B 后的余数。
void Unity_Modulo_float4(float4 A, float4 B, out float4 Out)
{
Out = fmod(A, B);
}
返回输入 In 的翻转符号值。正值变为负值,而负值变为正值。
void Unity_Negate_float4(float4 In, out float4 Out)
{
Out = -1 * In;
}
返回输入 In 的标准化值。输出矢量与输入 In 具有相同的方向,但长度为 1。
void Unity_Normalize_float4(float4 In, out float4 Out)
{
Out = normalize(In);
}
图像的分色需要将连续的色调渐变转换为几个较少色调的区域(从一个色调到另一个色调突然变化)。
此节点返回将输入 In 的值分色(也称为量化)为输入 Steps 指定的值数量的结果。
void Unity_Posterize_float4(float4 In, float4 Steps, out float4 Out)
{
Out = floor(In / (1 / Steps)) * (1 / Steps);
}
返回 1 除以输入 In 的结果。通过将 Method 设置为 Fast 可以在 Shader Model 5 上快速模拟此计算。
Default
void Unity_Reciprocal_float4(float4 In, out float4 Out)
{
Out = 1.0/In;
}
Fast(需要 Shader Model 5)
void Unity_Reciprocal_Fast_float4(float4 In, out float4 Out)
{
Out = rcp(In);
}
返回 1 除以输入 In 的平方根的结果。
void Unity_ReciprocalSquareRoot_float4(float4 In, out float4 Out)
{
Out = rsqrt(In);
}
返回两个输入值 A 和 B 之和。
void Unity_Add_float4(float4 A, float4 B, out float4 Out)
{
Out = A + B;
}
返回输入 A(被除数)除以输入 B(除数)的结果。
void Unity_Divide_float4(float4 A, float4 B, out float4 Out)
{
Out = A / B;
}
返回输入 A 乘以输入 B 的结果。如果两个输入都是矢量类型,则输出类型将是矢量类型且其维度与这些输入的评估类型相同。如果两个输入都是矩阵类型,则输出类型将是矩阵类型且其维度与这些输入的评估类型相同。如果一个输入是矢量类型而另一个是矩阵类型,则输出类型将是矢量类型且其维度与矢量类型输入相同。
Vector * Vector
void Unity_Multiply_float4_float4(float4 A, float4 B, out float4 Out)
{
Out = A * B;
}
Vector * Matrix
void Unity_Multiply_float4_float4x4(float4 A, float4x4 B, out float4 Out)
{
Out = mul(A, B);
}
Matrix * Matrix
void Unity_Multiply_float4x4_float4x4(float4x4 A, float4x4 B, out float4x4 Out)
{
Out = mul(A, B);
}
返回以输入 A 为底数并以输入 B 为指数的幂运算结果。
注意:如果输入 A 为负,输出可能不一致或为 NaN。
void Unity_Power_float4(float4 A, float4 B, out float4 Out)
{
Out = pow(A, B);
}
返回输入 In 的平方根。
void Unity_SquareRoot_float4(float4 In, out float4 Out)
{
Out = sqrt(In);
}
返回输入 A 减去输入 B 的结果。
void Unity_Subtract_float4(float4 A, float4 B, out float4 Out)
{
Out = A - B;
}
返回输入 In 相对于屏幕空间 X 坐标的偏导数。此节点只能在像素着色器阶段中使用。
void Unity_DDX_float4(float4 In, out float4 Out)
{
Out = ddx(In);
}
返回输入 In 分别相对于屏幕空间 X 坐标和屏幕空间 Y 坐标的两个偏导数之和。此节点只能在像素着色器阶段中使用。
void Unity_DDXY_float4(float4 In, out float4 Out)
{
Out = ddxy(In);
}
返回输入 In 相对于屏幕空间 Y 坐标的偏导数。此节点只能在像素着色器阶段中使用。
void Unity_DDY_float4(float4 In, out float4 Out)
{
Out = ddy(In);
}
返回在输入 A 到输入 B 范围内生成由输入 T 指定的插值的线性参数。
Inverse Lerp 是 Lerp 节点的逆运算。可用于确定 Lerp 的什么输入基于其输出。
例如,T 值为 1 时,0 和 2 之间的 Lerp 值为 0.5。因此,T 值为 0.5 时,0 和 2 之间的 Inverse Lerp 值为 1。
void Unity_InverseLerp_float4(float4 A, float4 B, float4 T, out float4 Out)
{
Out = (T - A)/(B - A);
}
返回按照输入 T 在输入 A 和输入 B 之间线性插值的结果。输入 T 的值限定在 0 到 1 的范围内。
例如,当输入 T 的值为 0 时,返回值等于输入 A 的值,为 1 时,返回值等于输入 B 的值,为 0.5 时,返回值等于两个输入 A 和 B 的中点。
void Unity_Lerp_float4(float4 A, float4 B, float4 T, out float4 Out)
{
Out = lerp(A, B, T);
}
如果输入 In 的值位于输入 Edge1 和 Edge2 的值之间,返回 0 和 1 之间的平滑埃尔米特插值结果。如果输入 In 的值小于输入 Step1 的值,返回 0;如果大于输入 Step2 的值,返回 1。
此节点类似于 Lerp 节点,但存在两个显著差异。首先,使用此节点时,由用户指定范围,返回值介于 0 和 1 之间。这可视为与 Lerp 节点相反。其次,此节点采用平滑埃尔米特插值,而不是线性插值。这意味着插值从开始后将逐渐加快速度,并在接近结束时减慢速度。这对于创建自然的动画、淡入淡出和其他过渡非常有用。
void Unity_Smoothstep_float4(float4 Edge1, float4 Edge2, float4 In, out float4 Out)
{
Out = smoothstep(Step1, Step2, In);
}
从四个输入矢量 M0、M1、M2 和 M3 构造方阵。此节点可用于生成矩阵 2x2、矩阵 3x3 和矩阵 4x4 类型的矩阵。
节点上的下拉选单可用于选择输入值是指定矩阵行还是列。
矩阵输出取自输入结构的左上角。这可用于从不同维度的矢量生成不同维度的方阵。
例如,将矢量 2 类型的值连接到输入 M0 和 M1 将会从输出 2x2 生成所需的矩阵。
Row
void Unity_MatrixConstruction_Row_float(float4 M0, float4 M1, float4 M2, float3 M3, out float4x4 Out4x4, out float3x3 Out3x3, out float2x2 Out2x2)
{
Out4x4 = float4x4(M0.x, M0.y, M0.z, M0.w, M1.x, M1.y, M1.z, M1.w, M2.x, M2.y, M2.z, M2.w, M3.x, M3.y, M3.z, M3.w);
Out3x3 = float3x3(M0.x, M0.y, M0.z, M1.x, M1.y, M1.z, M2.x, M2.y, M2.z);
Out2x2 = float2x2(M0.x, M0.y, M1.x, M1.y);
}
Column
void Unity_MatrixConstruction_Column_float(float4 M0, float4 M1, float4 M2, float3 M3, out float4x4 Out4x4, out float3x3 Out3x3, out float2x2 Out2x2)
{
Out4x4 = float4x4(M0.x, M1.x, M2.x, M3.x, M0.y, M1.y, M2.y, M3.y, M0.z, M1.z, M2.z, M3.z, M0.w, M1.w, M2.w, M3.w);
Out3x3 = float3x3(M0.x, M1.x, M2.x, M0.y, M1.y, M2.y, M0.z, M1.z, M2.z);
Out2x2 = float2x2(M0.x, M1.x, M0.y, M1.y);
}
返回由输入 In 定义的矩阵的行列式。可以视为矩阵描述的变换的缩放因子。
void Unity_MatrixDeterminant_float4x4(float4x4 In, out float Out)
{
Out = determinant(In);
}
将由输入 In 定义的方阵拆分为矢量。输出矢量维度由输入矩阵的维度定义。
节点上的下拉选单可用于选择输出值是取自输入矩阵的行还是列。
矩阵 2x2 或矩阵 3x3 类型的输入矩阵将在超出其维度的行(或列,具体取决于下拉选单的选择)中返回 0 值。
例如,将矩阵 2x2 类型连接到输入 In 将在输出字段 M0 和 M1 中返回正确的矢量 2 类型输出,并在输出 M2 和 M3 中返回 0 值。
float2 _MatrixSplit_M0 = float2(In[0].r, In[0].g);
float2 _MatrixSplit_M1 = float2(In[1].r, In[1].g);
float2 _MatrixSplit_M2 = float2(0, 0);
float2 _MatrixSplit_M3 = float2(0, 0);
返回由输入 In 定义的矩阵的转置值。这可以看作是在对角线上翻转矩阵的操作。结果是切换矩阵的行和列索引。
void Unity_MatrixTranspose_float4x4(float4x4 In, out float4x4 Out)
{
Out = transpose(In);
}
返回输入 In 在最小值和最大值(分别由输入 Min 和 Max 定义)之间钳制的结果。
void Unity_Clamp_float4(float4 In, float4 Min, float4 Max, out float4 Out)
{
Out = clamp(In, Min, Max);
}
返回输入 In 的小数部分;大于等于 0 且小于 1。
void Unity_Fraction_float4(float4 In, out float4 Out)
{
Out = frac(In);
}
返回两个输入值 A 和 B 中的最大值。
void Unity_Maximum_float4(float4 A, float4 B, out float4 Out)
{
Out = max(A, B);
}
返回两个输入值 A 和 B 中的最小值。
void Unity_Minimum_float4(float4 A, float4 B, out float4 Out)
{
Out = min(A, B);
}
返回从 1 减去输入 In 的结果。
void Unity_OneMinus_float4(float4 In, out float4 Out)
{
Out = 1 - In;
}
根据输入 Seed 返回由输入 Min 和 Max 分别定义的最小值和最大值之间的伪随机数值。
虽然输入 Seed 中的相同值将始终产生相同的输出值,但输出值本身将显示为随机数值。为便于根据 UV 输入生成随机数,输入 Seed 是矢量 2 值,但是对于大多数情况,Float 输入就足够了。
void Unity_RandomRange_float(float2 Seed, float Min, float Max, out float Out)
{
float randomno = frac(sin(dot(Seed, float2(12.9898, 78.233)))*43758.5453);
Out = lerp(Min, Max, randomno);
}
根据输入 In 值在输入 In Min Max 的 x 和 y 分量之间的线性插值,返回输入 Out Min Max 的 x 和 y 分量之间的值。
void Unity_Remap_float4(float4 In, float2 InMinMax, float2 OutMinMax, out float4 Out)
{
Out = OutMinMax.x + (In - InMinMax.x) * (OutMinMax.y - OutMinMax.x) / (InMinMax.y - InMinMax.x);
}
返回输入 In 在 0 和 1 之间钳制的值。
void Unity_Saturate_float4(float4 In, out float4 Out)
{
Out = saturate(In);
}
返回大于或等于输入 In 的值的最小整数。
void Unity_Ceiling_float4(float4 In, out float4 Out)
{
Out = ceil(In);
}
返回小于或等于输入 In 的值的最大整数。
void Unity_Floor_float4(float4 In, out float4 Out)
{
Out = floor(In);
}
返回输入 In 四舍五入到最接近的整数的值。
void Unity_Round_float4(float4 In, out float4 Out)
{
Out = round(In);
}
对于每个分量,如果输入 In 的值小于零,则返回 -1,如果等于零,则返回 0,如果大于零,则返回 1。
void Unity_Sign_float4(float4 In, out float4 Out)
{
Out = sign(In);
}
对于每个分量,如果输入 In 的值大于或等于输入 Edge 的值,则返回 1,否则返回 0。
void Unity_Step_float4(float4 Edge, float4 In, out float4 Out)
{
Out = step(Edge, In);
}
返回输入 In 的值的整数部分。例如,如果输入值为 1.7,此节点将返回值 1.0。
void Unity_Truncate_float4(float4 In, out float4 Out)
{
Out = trunc(In);
}
返回输入 In 的每个分量的反余弦值,作为相同维度和相等长度的矢量。每个分量都应在 -1 到 1 的范围内。
void Unity_Arccosine_float4(float4 In, out float4 Out)
{
Out = acos(In);
}
返回输入 In 的每个分量的反正弦值,作为相同维度和相等长度的矢量。每个分量都应在 -Pi/2 到 Pi/2 的范围内。
void Unity_Arcsine_float4(float4 In, out float4 Out)
{
Out = asin(In);
}
返回输入 In 的值的反正切值。每个分量都应在 -Pi/2 到 Pi/2 的范围内。
void Unity_Arctangent_float4(float4 In, out float4 Out)
{
Out = atan(In);
}
返回输入 A 和输入 B 的值的反正切值。输入值的符号(无论是正值还是负值)用于确定输出分量或通道在 -Pi 到 Pi 的范围内是正还是负。
void Unity_Arctangent2_float4(float4 A, float4 B, out float4 Out)
{
Out = atan2(A, B);
}
返回输入 In 的值的余弦值。
void Unity_Cosine_float4(float4 In, out float4 Out)
{
Out = cos(In);
}
返回输入 In 从度转换为弧度的值。
1 度等于约 0.0174533 弧度,360 度的完整旋转等于 2 Pi 弧度。
void Unity_DegreesToRadians_float4(float4 In, out float4 Out)
{
Out = radians(In);
}
返回输入 In 的双曲余弦值。
void Unity_HyperbolicCosine_float4(float4 In, out float4 Out)
{
Out = cosh(In);
}
返回输入 In 的双曲正弦值。
void Unity_HyperbolicSine_float4(float4 In, out float4 Out)
{
Out = sinh(In);
}
返回输入 In 的双曲正切值。
void Unity_HyperbolicTangent_float4(float4 In, out float4 Out)
{
Out = tanh(In);
}
返回输入 In 从弧度转换为度的值。1 弧度等于约 57.2958 度,2 Pi 弧度的完整旋转等于 360 度。
void Unity_RadiansToDegrees_float4(float4 In, out float4 Out)
{
Out = degrees(In);
}
返回输入 In 的值的正弦值。
void Unity_Sine_float4(float4 In, out float4 Out)
{
Out = sin(In);
}
返回输入 In 的值的正切值。
void Unity_Tangent_float4(float4 In, out float4 Out)
{
Out = tan(In);
}
返回输入 A 和输入 B 的值的差积。两个矢量的差积将得出垂直于两个输入矢量的第三个矢量。结果的大小等于两个输入的大小相乘,然后再乘以两个输入之间角度的正弦。可以使用”左手规则”确定结果矢量的方向。
void Unity_CrossProduct_float(float3 A, float3 B, out float3 Out)
{
Out = cross(A, B);
}
返回输入 A 和输入 B 的值之间的欧几里德距离。除了其他方面的用途,这对于计算空间中两点之间的距离很有用,通常用于计算有符号距离函数 (Signed Distance Function)。
void Unity_Distance_float4(float4 A, float4 B, out float Out)
{
Out = distance(A, B);
}
返回两个输入矢量 A 和 B 的点积或标量积。
点积的值等于将两个矢量的大小相乘,然后乘以矢量之间角度的余弦值。
对于标准化的输入矢量,如果它们指向完全相同的方向,Dot Product 节点返回 1;如果它们指向完全相反的方向,返回 -1;如果矢量彼此垂直,返回 0。
void Unity_DotProduct_float4(float4 A, float4 B, out float Out)
{
Out = dot(A, B);
}
菲涅耳效应 (Fresnel Effect) 是根据视角不同而在表面上产生不同反射率(接近掠射角时的反射光增多)的效果。Fresnel Effect 节点通过计算表面法线和视图方向之间的角度来模拟这一点。该角度越宽,返回值越大。这种效果通常用于实现在许多艺术风格中很常见的边缘光照。
void Unity_FresnelEffect_float(float3 Normal, float3 ViewDir, float Power, out float Out)
{
Out = pow((1.0 - saturate(dot(normalize(Normal), normalize(ViewDir)))), Power);
}
返回将输入 A 的值投影到与输入 B 的值平行的直线上的结果。
void Unity_Projection_float4(float4 A, float4 B, out float4 Out)
{
Out = B * dot(A, B) / dot(B, B);
}
返回使用输入 In 和表面法线 Normal 的反射矢量。
void Unity_Reflection_float4(float4 In, float4 Normal, out float4 Out)
{
Out = reflect(In, Normal);
}
返回输入 A 的值投影到与输入 B 的值正交或垂直的平面上的结果。拒绝矢量的值等于原始矢量(输入 A 的值)减去相同输入的 Projection 值。
void Unity_Rejection_float4(float4 A, float4 B, out float4 Out)
{
Out = A - (B * dot(A, B) / dot(B, B))
}
绕轴 Axis 将输入矢量 In 旋转值 Rotation。可以通过参数 Unit 选择旋转角度单位。
Radians
void Unity_RotateAboutAxis_Radians_float(float3 In, float3 Axis, float Rotation, out float3 Out)
{
float s = sin(Rotation);
float c = cos(Rotation);
float one_minus_c = 1.0 - c;
Axis = normalize(Axis);
float3x3 rot_mat =
{ one_minus_c * Axis.x * Axis.x + c, one_minus_c * Axis.x * Axis.y - Axis.z * s, one_minus_c * Axis.z * Axis.x + Axis.y * s,
one_minus_c * Axis.x * Axis.y + Axis.z * s, one_minus_c * Axis.y * Axis.y + c, one_minus_c * Axis.y * Axis.z - Axis.x * s,
one_minus_c * Axis.z * Axis.x - Axis.y * s, one_minus_c * Axis.y * Axis.z + Axis.x * s, one_minus_c * Axis.z * Axis.z + c
};
Out = mul(rot_mat, In);
}
Degrees
void Unity_RotateAboutAxis_Degrees_float(float3 In, float3 Axis, float Rotation, out float3 Out)
{
Rotation = radians(Rotation);
float s = sin(Rotation);
float c = cos(Rotation);
float one_minus_c = 1.0 - c;
Axis = normalize(Axis);
float3x3 rot_mat =
{ one_minus_c * Axis.x * Axis.x + c, one_minus_c * Axis.x * Axis.y - Axis.z * s, one_minus_c * Axis.z * Axis.x + Axis.y * s,
one_minus_c * Axis.x * Axis.y + Axis.z * s, one_minus_c * Axis.y * Axis.y + c, one_minus_c * Axis.y * Axis.z - Axis.x * s,
one_minus_c * Axis.z * Axis.x - Axis.y * s, one_minus_c * Axis.y * Axis.z + Axis.x * s, one_minus_c * Axis.z * Axis.z + c
};
Out = mul(rot_mat, In);
}
创建源自输入 Center 的球体遮罩。球体是使用 Distance 计算的,并使用 Radius 和 Hardness 输入进行修改。球体遮罩功能适用于 2D 和 3D 空间,并基于 Coords 输入中的矢量坐标。这些矢量坐标可以是类似世界空间位置的 3D 坐标,也可以是类似 UV 坐标的 2D 坐标。
void Unity_SphereMask_float4(float4 Coords, float4 Center, float Radius, float Hardness, out float4 Out)
{
Out = 1 - saturate((distance(Coords, Center) - Radius) / (1 - Hardness));
}
返回将输入值 (In) 从一个坐标空间变换为另一个坐标空间的结果。选择节点上的下拉选项来定义变换的起始空间和目标空间。
World 和 Absolute World
使用 World 和 Absolute World 空间选项来变换位置值的坐标空间。World 空间选项使用可编程渲染管线的默认世界空间来变换位置值。Absolute World 空间选项在所有可编程渲染管线中使用绝对世界空间来变换位置值。
如果使用 Transform 节点 变换的坐标空间不是用于位置值的坐标空间,Unity 建议使用 World 空间选项。对不代表位置的值使用 Absolute World 可能会导致意外行为。
World > World
float3 _Transform_Out = In;
World > Object
float3 _Transform_Out = TransformWorldToObject(In);
World > Tangent
float3x3 tangentTransform_World = float3x3(IN.WorldSpaceTangent, IN.WorldSpaceBiTangent, IN.WorldSpaceNormal);
float3 _Transform_Out = TransformWorldToTangent(In, tangentTransform_World);
World > View
float3 _Transform_Out = TransformWorldToView(In)
World > Absolute World
float3 _Transform_Out = GetAbsolutePositionWS(In);
Object > World
float3 _Transform_Out = TransformObjectToWorld(In);
Object > Object
float3 _Transform_Out = In;
Object > Tangent
float3x3 tangentTransform_World = float3x3(IN.WorldSpaceTangent, IN.WorldSpaceBiTangent, IN.WorldSpaceNormal);
float3 _Transform_Out = TransformWorldToTangent(TransformObjectToWorld(In), tangentTransform_World);
Object > View
float3 _Transform_Out = TransformWorldToView(TransformObjectToWorld(In));
Object > Absolute World
float3 _Transform_Out = GetAbsolutePositionWS(TransformObjectToWorld(In));
Tangent > World
float3x3 transposeTangent = transpose(float3x3(IN.WorldSpaceTangent, IN.WorldSpaceBiTangent, IN.WorldSpaceNormal));
float3 _Transform_Out = mul(In, transposeTangent).xyz;
Tangent > Object
float3x3 transposeTangent = transpose(float3x3(IN.WorldSpaceTangent, IN.WorldSpaceBiTangent, IN.WorldSpaceNormal));
float3 _Transform_Out = TransformWorldToObject(mul(In, transposeTangent).xyz);
Tangent > Tangent
float3 _Transform_Out = In;
Tangent > View
float3x3 transposeTangent = transpose(float3x3(IN.WorldSpaceTangent, IN.WorldSpaceBiTangent, IN.WorldSpaceNormal));
float3 _Transform_Out = TransformWorldToView(mul(In, transposeTangent).xyz);
Tangent > Absolute World
float3x3 transposeTangent = transpose(float3x3(IN.WorldSpaceTangent, IN.WorldSpaceBiTangent, IN.WorldSpaceNormal));
float3 _Transform_Out = GetAbsolutePositionWS(mul(In, transposeTangent)).xyz;
View > World
float3 _Transform_Out = mul(UNITY_MATRIX_I_V, float4(In, 1)).xyz;
View > Object
float3 _Transform_Out = TransformWorldToObject(mul(UNITY_MATRIX_I_V, float4(In, 1) ).xyz);
View > Tangent
float3x3 tangentTransform_World = float3x3(IN.WorldSpaceTangent, IN.WorldSpaceBiTangent, IN.WorldSpaceNormal);
float3 _Transform_Out = TransformWorldToTangent(mul(UNITY_MATRIX_I_V, float4(In, 1) ).xyz, tangentTransform_World);
View > View
float3 _Transform_Out = In;
View > Absolute World
float3 _Transform_Out = GetAbsolutePositionWS(mul(UNITY_MATRIX_I_V, float4(In, 1))).xyz;
Absolute World > World
float3 _Transform_Out = GetCameraRelativePositionWS(In);
Absolute World > Object
float3 _Transform_Out = TransformWorldToObject(In);
Absolute World > Tangent
float3x3 tangentTransform_World = float3x3(IN.WorldSpaceTangent, IN.WorldSpaceBiTangent, IN.WorldSpaceNormal);
float3 _Transform_Out = TransformWorldToTangent(In, tangentTransform_World);
Absolute World > View
float3 _Transform_Out = TransformWorldToView(In)
Absolute World > Absolute World
float3 _Transform_Out = In;
返回输入 In 的值的正弦值。为表现变化,正弦波的幅度中将添加伪随机噪声(处于输入 Min Max 确定的范围内)。
void Unity_NoiseSineWave_float4(float4 In, float2 MinMax, out float4 Out)
{
float sinIn = sin(In);
float sinInOffset = sin(In + 1.0);
float randomno = frac(sin((sinIn - sinInOffset) * (12.9898 + 78.233))*43758.5453);
float noise = lerp(MinMax.x, MinMax.y, randomno);
Out = sinIn + noise;
}
从输入 In 的值返回锯齿波。
void Unity_SawtoothWave_float4(float4 In, out float4 Out)
{
Out = 2 * (In - floor(0.5 + In));
}
从输入 In 的值返回方波。
void Unity_SquareWave_float4(float4 In, out float4 Out)
{
Out = 1.0 - 2.0 * round(frac(In));
}
从中输入的值返回三角形波。
void Unity_TriangleWave_float4(float4 In, out float4 Out)
{
Out = 2.0 * abs( 2 * (In - floor(0.5 + In)) ) - 1.0;
}
根据输入 UV 生成渐变或柏林噪声。生成噪声的比例由输入 Scale 控制。
float2 unity_gradientNoise_dir(float2 p)
{
p = p % 289;
float x = (34 * p.x + 1) * p.x % 289 + p.y;
x = (34 * x + 1) * x % 289;
x = frac(x / 41) * 2 - 1;
return normalize(float2(x - floor(x + 0.5), abs(x) - 0.5));
}
float unity_gradientNoise(float2 p)
{
float2 ip = floor(p);
float2 fp = frac(p);
float d00 = dot(unity_gradientNoise_dir(ip), fp);
float d01 = dot(unity_gradientNoise_dir(ip + float2(0, 1)), fp - float2(0, 1));
float d10 = dot(unity_gradientNoise_dir(ip + float2(1, 0)), fp - float2(1, 0));
float d11 = dot(unity_gradientNoise_dir(ip + float2(1, 1)), fp - float2(1, 1));
fp = fp * fp * fp * (fp * (fp * 6 - 15) + 10);
return lerp(lerp(d00, d01, fp.y), lerp(d10, d11, fp.y), fp.x);
}
void Unity_GradientNoise_float(float2 UV, float Scale, out float Out)
{
Out = unity_gradientNoise(UV * Scale) + 0.5;
}
根据输入 UV 生成简单噪声或 Value 噪声。生成噪声的比例由输入 Scale 控制。
inline float unity_noise_randomValue (float2 uv)
{
return frac(sin(dot(uv, float2(12.9898, 78.233)))*43758.5453);
}
inline float unity_noise_interpolate (float a, float b, float t)
{
return (1.0-t)*a + (t*b);
}
inline float unity_valueNoise (float2 uv)
{
float2 i = floor(uv);
float2 f = frac(uv);
f = f * f * (3.0 - 2.0 * f);
uv = abs(frac(uv) - 0.5);
float2 c0 = i + float2(0.0, 0.0);
float2 c1 = i + float2(1.0, 0.0);
float2 c2 = i + float2(0.0, 1.0);
float2 c3 = i + float2(1.0, 1.0);
float r0 = unity_noise_randomValue(c0);
float r1 = unity_noise_randomValue(c1);
float r2 = unity_noise_randomValue(c2);
float r3 = unity_noise_randomValue(c3);
float bottomOfGrid = unity_noise_interpolate(r0, r1, f.x);
float topOfGrid = unity_noise_interpolate(r2, r3, f.x);
float t = unity_noise_interpolate(bottomOfGrid, topOfGrid, f.y);
return t;
}
void Unity_SimpleNoise_float(float2 UV, float Scale, out float Out)
{
float t = 0.0;
float freq = pow(2.0, float(0));
float amp = pow(0.5, float(3-0));
t += unity_valueNoise(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;
freq = pow(2.0, float(1));
amp = pow(0.5, float(3-1));
t += unity_valueNoise(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;
freq = pow(2.0, float(2));
amp = pow(0.5, float(3-2));
t += unity_valueNoise(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;
Out = t;
}
根据输入 UV 生成 Voronoi 或 Worley 噪声。Voronoi 噪声是通过计算像素和点阵之间的距离生成的。通过使这些点偏移由输入 Angle Offset 控制的伪随机数,可以生成一组单元。这些单元的规模以及产生的噪声由输入 Cell Density 控制。输出 Cells 包含原始单元数据。
inline float2 unity_voronoi_noise_randomVector (float2 UV, float offset)
{
float2x2 m = float2x2(15.27, 47.63, 99.41, 89.98);
UV = frac(sin(mul(UV, m)) * 46839.32);
return float2(sin(UV.y*+offset)*0.5+0.5, cos(UV.x*offset)*0.5+0.5);
}
void Unity_Voronoi_float(float2 UV, float AngleOffset, float CellDensity, out float Out, out float Cells)
{
float2 g = floor(UV * CellDensity);
float2 f = frac(UV * CellDensity);
float t = 8.0;
float3 res = float3(8.0, 0.0, 0.0);
for(int y=-1; y<=1; y++)
{
for(int x=-1; x<=1; x++)
{
float2 lattice = float2(x,y);
float2 offset = unity_voronoi_noise_randomVector(lattice + g, AngleOffset);
float d = distance(lattice + offset, f);
if(d < res.x)
{
res = float3(d, offset.x, offset.y);
Out = res.x;
Cells = res.y;
}
}
}
}
以输入 Width 和 Height 指定的大小基于输入 UV 生成椭圆形状。通过连接 Tiling And Offset 节点可以偏移或平铺生成的形状。请注意,为了保留在 UV 空间内偏移形状的能力,如果经过平铺,形状将不会自动重复。要实现重复点效果,应首先通过 Fraction 节点连接输入。
注意:此节点只能在片元着色器阶段中使用。
void Unity_Ellipse_float(float2 UV, float Width, float Height, out float4 Out)
{
float d = length((UV * 2 - 1) / float2(Width, Height));
Out = saturate((1 - d) / fwidth(d));
}
以输入 Width 和 Height 指定的大小基于输入 UV 生成正多边形。多边形的边数由输入 Sides 确定。通过连接 Tiling And Offset 节点可以偏移或平铺生成的形状。请注意,为了保留在 UV 空间内偏移形状的能力,如果经过平铺,形状将不会自动重复。要实现重复多边形效果,应首先通过 Fraction 节点连接输入。
注意:此节点只能在片元着色器阶段中使用。
void Unity_Polygon_float(float2 UV, float Sides, float Width, float Height, out float Out)
{
float pi = 3.14159265359;
float aWidth = Width * cos(pi / Sides);
float aHeight = Height * cos(pi / Sides);
float2 uv = (UV * 2 - 1) / float2(aWidth, aHeight);
uv.y *= -1;
float pCoord = atan2(uv.x, uv.y);
float r = 2 * pi / Sides;
float distance = cos(floor(0.5 + pCoord / r) * r - pCoord) * length(uv);
Out = saturate((1 - distance) / fwidth(distance));
}
以输入 Width 和 Height 指定的大小基于输入 UV 生成矩形。通过连接 Tiling And Offset 节点可以偏移或平铺生成的形状。请注意,为了保留在 UV 空间内偏移形状的能力,如果经过平铺,形状将不会自动重复。要实现重复矩形效果,应首先通过 Fraction 节点连接输入。
注意:此节点只能在片元着色器阶段中使用。
void Unity_Rectangle_float(float2 UV, float Width, float Height, out float Out)
{
float2 d = abs(UV * 2 - 1) - float2(Width, Height);
d = 1 - d / fwidth(d);
Out = saturate(min(d.x, d.y));
}
以输入 Width 和 Height 指定的大小基于输入 UV 生成圆角多边形。输入 Sides 确定多边形的边数,输入 Roundness 定义每个角的圆度。
通过连接 Tiling And Offset 节点可以偏移或平铺该形状。为了保留在 UV 空间内偏移形状的能力,如果进行平铺,形状将不会自动重复。要实现重复圆角多边形效果,应首先通过 Fraction 节点连接 UV 输入。
Rounded Polygon 节点只能在片元着色器阶段使用。
void RoundedPolygon_Func_float(float2 UV, float Width, float Height, float Sides, float Roundness, out float Out)
{
UV = UV * 2. + float2(-1.,-1.);
float epsilon = 1e-6;
UV.x = UV.x / ( Width + (Width==0)*epsilon);
UV.y = UV.y / ( Height + (Height==0)*epsilon);
Roundness = clamp(Roundness, 1e-6, 1.);
float i_sides = floor( abs( Sides ) );
float fullAngle = 2. * PI / i_sides;
float halfAngle = fullAngle / 2.;
float opositeAngle = HALF_PI - halfAngle;
float diagonal = 1. / cos( halfAngle );
// Chamfer values
float chamferAngle = Roundness * halfAngle; // Angle taken by the chamfer
float remainingAngle = halfAngle - chamferAngle; // Angle that remains
float ratio = tan(remainingAngle) / tan(halfAngle); // This is the ratio between the length of the polygon's triangle and the distance of the chamfer center to the polygon center
// Center of the chamfer arc
float2 chamferCenter = float2(
cos(halfAngle) ,
sin(halfAngle)
)* ratio * diagonal;
// starting of the chamfer arc
float2 chamferOrigin = float2(
1.,
tan(remainingAngle)
);
// Using Al Kashi algebra, we determine:
// The distance distance of the center of the chamfer to the center of the polygon (side A)
float distA = length(chamferCenter);
// The radius of the chamfer (side B)
float distB = 1. - chamferCenter.x;
// The refence length of side C, which is the distance to the chamfer start
float distCref = length(chamferOrigin);
// This will rescale the chamfered polygon to fit the uv space
// diagonal = length(chamferCenter) + distB;
float uvScale = diagonal;
UV *= uvScale;
float2 polaruv = float2 (
atan2( UV.y, UV.x ),
length(UV)
);
polaruv.x += HALF_PI + 2*PI;
polaruv.x = fmod( polaruv.x + halfAngle, fullAngle );
polaruv.x = abs(polaruv.x - halfAngle);
UV = float2( cos(polaruv.x), sin(polaruv.x) ) * polaruv.y;
// Calculate the angle needed for the Al Kashi algebra
float angleRatio = 1. - (polaruv.x-remainingAngle) / chamferAngle;
// Calculate the distance of the polygon center to the chamfer extremity
float distC = sqrt( distA*distA + distB*distB - 2.*distA*distB*cos( PI - halfAngle * angleRatio ) );
Out = UV.x;
float chamferZone = ( halfAngle - polaruv.x ) < chamferAngle;
Out = lerp( UV.x, polaruv.y / distC, chamferZone );
// Output this to have the shape mask instead of the distance field
Out = saturate((1 - Out) / fwidth(Out));
}
以输入 Width 和 Height 指定的大小基于输入 UV 生成圆角矩形。每个角的半径由输入 Radius 定义。通过连接 Tiling And Offset 节点可以偏移或平铺生成的形状。请注意,为了保留在 UV 空间内偏移形状的能力,如果经过平铺,形状将不会自动重复。要实现重复圆角矩形效果,应首先通过 Fraction 节点连接输入。
注意:此节点只能在片元着色器阶段中使用。
void Unity_RoundedRectangle_float(float2 UV, float Width, float Height, float Radius, out float Out)
{
Radius = max(min(min(abs(Radius * 2), abs(Width)), abs(Height)), 1e-5);
float2 uv = abs(UV * 2 - 1) - float2(Width, Height) + Radius;
float d = length(max(0, uv)) / Radius;
Out = saturate((1 - d) / fwidth(d));
}
根据输入 UV 在输入 Color A 和 Color B 之间生成交替颜色的棋盘格。棋盘比例由输入 Frequency 定义。
void Unity_Checkerboard_float(float2 UV, float3 ColorA, float3 ColorB, float2 Frequency, out float3 Out)
{
UV = (UV.xy + 0.5) * Frequency;
float4 derivatives = float4(ddx(UV), ddy(UV));
float2 duv_length = sqrt(float2(dot(derivatives.xz, derivatives.xz), dot(derivatives.yw, derivatives.yw)));
float width = 1.0;
float2 distance3 = 4.0 * abs(frac(UV + 0.25) - 0.5) - width;
float2 scale = 0.35 / duv_length.xy;
float freqLimiter = sqrt(clamp(1.1f - max(duv_length.x, duv_length.y), 0.0, 1.0));
float2 vector_alpha = clamp(distance3 * scale.xy, -1.0, 1.0);
float alpha = saturate(0.5f + 0.5f * vector_alpha.x * vector_alpha.y * freqLimiter);
Out = lerp(ColorA, ColorB, alpha.xxx);
}
如果输入 In 的所有分量都不为零,则返回 true。这对于分支 很有用。
void Unity_All_float4(float4 In, out float Out)
{
Out = all(In);
}
如果输入 A 和 B 均为 true,则返回 true。这对于分支 很有用。
void Unity_And(float A, float B, out float Out)
{
Out = A && B;
}
如果输入 In 的任何分量不为零,则返回 true。这对于分支 很有用。
void Unity_Any_float4(float4 In, out float Out)
{
Out = any(In);
}
为着色器提供动态分支。如果输入 Predicate 为 true,则返回输出将等于输入 True,否则它将等于输入 False。这是根据着色器阶段按照每个顶点或每个像素确定的。分支的两边都将在着色器中进行计算,没有使用的分支将被丢弃。
void Unity_Branch_float4(float Predicate, float4 True, float4 False, out float4 Out)
{
Out = Predicate ?True : False;
}
根据下拉选单上选择的条件比较两个输入值 A 和 B。这通常用作 Branch 节点的输入。
Equal
void Unity_Comparison_Equal_float(float A, float B, out float Out)
{
Out = A == B ?1 : 0;
}
NotEqual
void Unity_Comparison_NotEqual_float(float A, float B, out float Out)
{
Out = A != B ?1 : 0;
}
Less
void Unity_Comparison_Less_float(float A, float B, out float Out)
{
Out = A < B ?1 : 0;
}
LessOrEqual
void Unity_Comparison_LessOrEqual_float(float A, float B, out float Out)
{
Out = A <= B ?1 : 0;
}
Greater
void Unity_Comparison_Greater_float(float A, float B, out float Out)
{
Out = A > B ?1 : 0;
}
GreaterOrEqual
void Unity_Comparison_GreaterOrEqual_float(float A, float B, out float Out)
{
Out = A >= B ?1 : 0;
}
如果输入 In 是无限值,则返回 true。这对于分支 (Branching) 很有用。
void Unity_IsInfinite_float(float In, out float Out)
{
Out = isinf(In);
}
如果输入 In 不是数字 (NaN),则返回 true。这对于分支 (Branching) 很有用。
void Unity_IsNan_float(float In, out float Out)
{
Out = (In < 0.0 || In > 0.0 || In == 0.0) ?0 : 1;
}
如果输入 A 和 B 均为 false,则返回 true。这对于分支 (Branching) 很有用。
void Unity_Nand_float(float A, float B, out float Out)
{
Out = !A && !B;
}
返回输入 In 的相反值。如果 In 为 true,则输出为 false,否则为 true。这对于分支 (Branching) 很有用。
void Unity_NormalUnpack_float(float In, out float Out)
{
Out = !In;
}
如果输入 A 和 B 任一项为 true,则返回 true。这对于分支 (Branching) 很有用。
void Unity_Or_float(float In, out float Out)
{
Out = A || B;
}
Emission 节点允许在 Shader Graph 中应用发射。
发射单位
可以使用两个物理光单位来控制发射的强度:
曝光权重
可以使用曝光权重 (Exposure Weight) 来确定曝光对发射的影响。此值介于 0 到 1 之间。值为 0 表示曝光不影响发射的此部分。值为 1 表示曝光完全影响发射的此部分。
该节点将变形应用于归一化的 IrisUV 坐标,以模拟瞳孔的打开和关闭。
该节点在对象空间中执行注视光线的折射,并返回获得的对象空间位置。这用于模拟注视眼睛时可以看到的折射。
可用于直观地验证当前瞳孔半径的 Debug 节点。
计算角膜缘环的强度,这是眼睛的明暗特征。
应用虹膜中心的偏移,因为现实世界中的眼睛永远不会对称且居中。
将虹膜颜色限制为给定的颜色。这在折射光线到达角膜内部的情况下很有用。
该节点将角膜/虹膜的对象位转换为 UV 采样坐标。
该节点融合了虹膜和巩膜的所有属性,从而将它们提供给主节点。
计算巩膜缘环的强度,这是眼睛的明暗特征。
该节点将巩膜的对象位转换为 UV 采样坐标。
自定义函数节点用于在 Shader Graph 中注入自定义 HLSL 代码。这样,您可在需要时提供额外的控制级别(例如,进行一些细粒度的优化)。可以使用 string 模式直接将较小的函数写入图形,或者引用外部的 HLSL include 文件。还可以使用 Custom Port Menu 在节点本身上定义自己的输入和输出端口。
您可以使用 Keyword 节点在 Shader Graph 中创建一个静态分支,该分支引用一个位于 Blackboard 上的关键字。Keyword 节点的外观,包括其可用端口,会根据它引用的关键字而变化。
提供预览窗口并传递输入值而无需修改。如果用户通常更喜欢折叠节点预览,则可以使用此节点在 Shader Graph 中的特定点提供预览。
void Unity_Preview_float4(float4 In, out float4 Out)
{
Out = In;
}
提供对子图形资源的引用。参考节点上的所有端口都由子图形资源中定义的属性和输出进行定义。这对于在图形之间共享功能或在图形中复制相同功能非常有用。
用于 Sub Graph 节点的预览由其 Output 节点的第一个端口决定。第一个端口有效的数据类型是 Float、Vector 2、Vector 3、Vector 4、Matrix2、Matrix3、Matrix4 和 Boolean。任何其他数据类型在预览着色器和子图形中都会产生错误。
子图形节点和着色器阶段
如果子图形中的节点指定了一个着色器阶段(例如 Sample Texture 2D 节点指定片元着色器阶段),则整个子图形现在将锁定到该阶段。因此,引用该图形的 Sub Graph 节点也将锁定到该着色器阶段。
此外,当连接到 Sub Graph 节点上的输出端口的边流入主节点上的端口时,该 Sub Graph 节点现在将锁定到该主节点端口的着色器阶段。
使用向输入 UV 提供的 UV 创建翻页或纹理帧动画。纹理层上的区块数量由输入 Width 和 Height 的值定义。当前区块的索引由输入 Tile 的值定义。
此节点可用于创建纹理动画功能,通常用于粒子效果和精灵,方法是将 Time 提供给输入 Tile 并输出到 Texture Sampler 的 UV 输入字段。
UV 数据通常在 0 到 1 的范围内,从 UV 空间的左下角开始。这可以通过 UV 预览左下角的黑色值看出。默认情况下,由于翻页通常从左上角开始,因此会启用参数 Invert Y,但可以通过切换 Invert X 和 Invert Y 参数来更改翻页的方向。
float2 _Flipbook_Invert = float2(FlipX, FlipY);
void Unity_Flipbook_float(float2 UV, float Width, float Height, float Tile, float2 Invert, out float2 Out)
{
Tile = fmod(Tile, Width * Height);
float2 tileCount = float2(1.0, 1.0) / float2(Width, Height);
float tileY = abs(Invert.y * Height - (floor(Tile * tileCount.x) + Invert.y * 1));
float tileX = abs(Invert.x * Width - ((Tile - Width * floor(Tile * tileCount.x)) + Invert.x * 1));
Out = (UV + float2(tileX, tileY)) * tileCount;
}
将输入 UV 的值转换为极坐标。在数学中,极坐标系是二维坐标系,其中平面上的每个点由相对于参考点的距离和相对于参考方向的角度确定。
产生的效果是 UV 输入的 X 通道转换为相对于指定点(由输入 Center 的值指定)的距离值,而该相同输入的 Y 通道转换为相对于该点的旋转角度值。
这些值可以分别由输入 Radial Scale 和 Length Scale 的值进行缩放。
void Unity_PolarCoordinates_float(float2 UV, float2 Center, float RadialScale, float LengthScale, out float2 Out)
{
float2 delta = UV - Center;
float radius = length(delta) * 2 * RadialScale;
float angle = atan2(delta.x, delta.y) * 1.0/6.28 * LengthScale;
Out = float2(radius, angle);
}
将类似于波的径向剪切变形效果应用于输入 UV 的值。变形效果的中心参考点由输入 Center 定义,而效果的整体强度由输入 Strength 的值定义。输入 Offset 可用于偏移结果的各个通道。
void Unity_RadialShear_float(float2 UV, float2 Center, float Strength, float2 Offset, out float2 Out)
{
float2 delta = UV - Center;
float delta2 = dot(delta.xy, delta.xy);
float2 delta_offset = delta2 * Strength;
Out = UV + float2(delta.y, -delta.x) * delta_offset + Offset;
}
围绕输入 Center 定义的参考点将输入 UV 的值旋转输入 Rotation 的大小。可以通过参数 Unit 选择旋转角度单位。
Radians
void Unity_Rotate_Radians_float(float2 UV, float2 Center, float Rotation, out float2 Out)
{
UV -= Center;
float s = sin(Rotation);
float c = cos(Rotation);
float2x2 rMatrix = float2x2(c, -s, s, c);
rMatrix *= 0.5;
rMatrix += 0.5;
rMatrix = rMatrix * 2 - 1;
UV.xy = mul(UV.xy, rMatrix);
UV += Center;
Out = UV;
}
Degrees
void Unity_Rotate_Degrees_float(float2 UV, float2 Center, float Rotation, out float2 Out)
{
Rotation = Rotation * (3.1415926f/180.0f);
UV -= Center;
float s = sin(Rotation);
float c = cos(Rotation);
float2x2 rMatrix = float2x2(c, -s, s, c);
rMatrix *= 0.5;
rMatrix += 0.5;
rMatrix = rMatrix * 2 - 1;
UV.xy = mul(UV.xy, rMatrix);
UV += Center;
Out = UV;
}
将类似于鱼眼镜头的球形变形效果应用于输入 UV 的值。变形效果的中心参考点由输入 Center 定义,而效果的整体强度由输入 Strength 的值定义。输入 Offset 可用于偏移结果的各个通道。
void Unity_Spherize_float(float2 UV, float2 Center, float Strength, float2 Offset, out float2 Out)
{
float2 delta = UV - Center;
float delta2 = dot(delta.xy, delta.xy);
float delta4 = delta2 * delta2;
float2 delta_offset = delta4 * Strength;
Out = UV + delta * delta_offset + Offset;
}
分别根据输入 Tiling 和 Offset 来平铺和偏移输入 UV 的值。这通常用于细节贴图和随时间滚动纹理。
void Unity_TilingAndOffset_float(float2 UV, float2 Tiling, float2 Offset, out float2 Out)
{
Out = UV * Tiling + Offset;
}
Triplanar 是一种通过在世界空间中投影来生成 UV 并对纹理进行采样的方法。输入纹理被采样 3 次,在世界 x、y 和 z 轴的每一个轴中都采样一次,然后生成的信息被平面投影到模型上,并由法线或表面角度混合。生成的 UV 可以使用输入 Tile 进行缩放,并可以使用输入 Blend 控制最终的混合强度。Blend 控制法线影响每个平面样本混合的方式,应大于或等于 0。Blend 越大,最接近法线朝向的平面对样本的贡献越大。(最大混合指数在 17 到 158 之间,具体取决于平台和节点的精度。)无论法线方向如何,Blend 为 0 会使每个平面获得相等的权重。可以通过覆盖输入 Position和 Normal 来修改投影。这通常用于大型模型(例如地形,这种情况下手动创建 UV 坐标会有问题或性能不佳)的纹理。
可以使用 Type 下拉选单来切换输入纹理的预期类型。如果设置为 Normal,则法线将转换为世界空间,因此可以构造新的切线,然后在输出之前将其转换回切线空间。
如果在包含自定义函数节点或子图形的图形中使用此节点时遇到纹理采样错误,可以通过升级到 10.3 或更高版本来解决这些问题。
注意:此节点只能在片元着色器阶段中使用。
Default
float3 Node_UV = Position * Tile;
float3 Node_Blend = pow(abs(Normal), Blend);
Node_Blend /= dot(Node_Blend, 1.0);
float4 Node_X = SAMPLE_TEXTURE2D(Texture, Sampler, Node_UV.zy);
float4 Node_Y = SAMPLE_TEXTURE2D(Texture, Sampler, Node_UV.xz);
float4 Node_Z = SAMPLE_TEXTURE2D(Texture, Sampler, Node_UV.xy);
float4 Out = Node_X * Node_Blend.x + Node_Y * Node_Blend.y + Node_Z * Node_Blend.z;
Normal
float3 Node_UV = Position * Tile;
float3 Node_Blend = max(pow(abs(Normal), Blend), 0);
Node_Blend /= (Node_Blend.x + Node_Blend.y + Node_Blend.z ).xxx;
float3 Node_X = UnpackNormal(SAMPLE_TEXTURE2D(Texture, Sampler, Node_UV.zy));
float3 Node_Y = UnpackNormal(SAMPLE_TEXTURE2D(Texture, Sampler, Node_UV.xz));
float3 Node_Z = UnpackNormal(SAMPLE_TEXTURE2D(Texture, Sampler, Node_UV.xy));
Node_X = float3(Node_X.xy + Normal.zy, abs(Node_X.z) * Normal.x);
Node_Y = float3(Node_Y.xy + Normal.xz, abs(Node_Y.z) * Normal.y);
Node_Z = float3(Node_Z.xy + Normal.xy, abs(Node_Z.z) * Normal.z);
float4 Out = float4(normalize(Node_X.zyx * Node_Blend.x + Node_Y.xzy * Node_Blend.y + Node_Z.xyz * Node_Blend.z), 1);
float3x3 Node_Transform = float3x3(IN.WorldSpaceTangent, IN.WorldSpaceBiTangent, IN.WorldSpaceNormal);
Out.rgb = TransformWorldToTangent(Out.rgb, Node_Transform);
将类似于黑洞的旋转变形效果应用于输入 UV 的值。变形效果的中心参考点由输入 Center 定义,而效果的整体强度由输入 Strength 的值定义。输入 Offset 可用于偏移结果的各个通道。
void Unity_Twirl_float(float2 UV, float2 Center, float Strength, float2 Offset, out float2 Out)
{
float2 delta = UV - Center;
float angle = Strength * length(delta);
float x = cos(angle) * delta.x - sin(angle) * delta.y;
float y = sin(angle) * delta.x + cos(angle) * delta.y;
Out = float2(x + Center.x + Offset.x, y + Center.y + Offset.y);
}
视差贴图 (Parallax Mapping) 节点允许创建视差效果,这种效果可以对材质的 UV 和深度进行移位以便在材质内产生深度感。此实现使用不考虑遮挡的单步过程。有关呈现的效果的信息,请参阅高度贴图页。
如果在包含自定义函数节点或子图形的图形中使用此节点时遇到纹理采样错误,可以通过升级到 10.3 或更高版本来解决这些问题。
float2 _ParallaxMapping_ParallaxUVs = UVs.xy + ParallaxMapping(Heightmap, Heightmap_Sampler, IN.TangentSpaceViewDirection, Amplitude * 0.01, UVs.xy);
视差遮挡贴图 (Parallax Occlusion Mapping, POM) 节点允许创建视差效果,这种效果可以对材质的 UV 和深度进行移位以便在材质内产生深度感。
如果在包含自定义函数节点或子图形的图形中使用此节点时遇到纹理采样错误,可以通过升级到 10.3 或更高版本来解决这些问题。
float3 ParallaxOcclusionMapping_ViewDir = IN.TangentSpaceViewDirection * GetDisplacementObjectScale().xzy;
float ParallaxOcclusionMapping_NdotV = ParallaxOcclusionMapping_ViewDir.z;
float ParallaxOcclusionMapping_MaxHeight = Amplitude * 0.01;
// Transform the view vector into the UV space.
float3 ParallaxOcclusionMapping_ViewDirUV = normalize(float3(ParallaxOcclusionMapping_ViewDir.xy * ParallaxOcclusionMapping_MaxHeight, ParallaxOcclusionMapping_ViewDir.z)); // TODO: skip normalize
PerPixelHeightDisplacementParam ParallaxOcclusionMapping_POM;
ParallaxOcclusionMapping_POM.uv = UVs.xy;
float ParallaxOcclusionMapping_OutHeight;
float2 _ParallaxOcclusionMapping_ParallaxUVs = UVs.xy + ParallaxOcclusionMapping(Lod, Lod_Threshold, Steps, ParallaxOcclusionMapping_ViewDirUV, ParallaxOcclusionMapping_POM, ParallaxOcclusionMapping_OutHeight);
float _ParallaxOcclusionMapping_PixelDepthOffset = (ParallaxOcclusionMapping_MaxHeight - ParallaxOcclusionMapping_OutHeight * ParallaxOcclusionMapping_MaxHeight) / max(ParallaxOcclusionMapping_NdotV, 0.0001);