specular anisotropic实现

blender、UE、Unity

anisotropic即不同方向上不均匀的特性。在计算机图形学的材质方面,specular、transmission、subsuface、coat均可能为anisotropic。

常用的计算specular BRDF的Cook-Torrance微面模型的D项GGX

isotropic GGX: \[ D_{GGX}(H) = \frac{\alpha^2}{\pi((N\cdot H)^2 (\alpha^2 - 1) + 1)^2} \] anisotropic GGX: \[ D_{GGXaniso}(H) = \frac{1}{\pi \alpha_x \alpha_y} \frac{1}{ \left( \frac{(X \cdot H)^2}{\alpha_x^2} + \frac{(Y \cdot H)^2}{\alpha_y^2} + (N\cdot H)^2 \right)^2 } \] 其中\(x\)\(y\)分别代表切线和副切线方向,\(\alpha_x\)\(\alpha_y\)即对应方向上的roughness。

设anisotropic值为\(a\)、roughness值为\(r\),不同的\(\alpha_x\)\(\alpha_y\)参数化方法[1]如下:

  1. Burley 2012 (Disney model)

\[ aspect=\sqrt{1-0.9a} \]

\[ \alpha_x=\frac{r^2}{aspect} \]

\[ \alpha_y=r^2\cdot aspect \]

  1. Georgiev 2019 (Standard Surface)

\[ \alpha_x = \min(\frac{r^2}{\sqrt{1-a}}, 1.0) \]

\[ \alpha_y = r^2 \sqrt{1-a} \]

  1. Kulla 2017 (Sony Pictures Imageworks)

\[ \alpha_x = r^2 (1 + a) \]

\[ \alpha_y = r^2 (1 - a) \]

  1. Neubelt 2013 (The Order: 1886)

\[ \alpha_x = r^2 \]

\[ \alpha_y = \mathrm{lerp}(0, r^2, 1 - a) \]

  1. Kutz 2021 (Adobe Standard Material)

\[ \alpha_x = r^2 + a^4 \]

\[ \alpha_y = r^2 \]

  1. OpenPBR proposed mapping 2023

\[ \alpha_x = r^2 \sqrt{\frac{2}{1 + (1 - a)^2}} \]

\[ \alpha_y = (1 - a)\alpha_x \]

Blender的cycles使用Burley 2012:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// intern\cycles\kernel\osl\shaders\node_principled_bsdf.osl

// Roughness默认为0.5

float r2 = clamp(Roughness, 0.0, 1.0);
r2 = r2 * r2;
float alpha_x = r2, alpha_y = r2;

vector T = Tangent;
if (Anisotropic > 0.0) {
float aspect = sqrt(1.0 - clamp(Anisotropic, 0.0, 1.0) * 0.9);
alpha_x /= aspect;
alpha_y *= aspect;
if (AnisotropicRotation != 0.0)
T = rotate(T, AnisotropicRotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
}

UE默认使用Kulla 2017:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Engine\Shaders\Private\BRDF.ush

// Alpha为Roughness的平方

// Convert a roughness and an anisotropy factor into GGX alpha values respectively for the major and minor axis of the tangent frame
void GetAnisotropicRoughness(float Alpha, float Anisotropy, out float ax, out float ay)
{
#if 1
// Anisotropic parameters: ax and ay are the roughness along the tangent and bitangent
// Kulla 2017, "Revisiting Physically Based Shading at Imageworks"
ax = max(Alpha * (1.0 + Anisotropy), 0.001f);
ay = max(Alpha * (1.0 - Anisotropy), 0.001f);
#else
float K = sqrt(1.0f - 0.95f * Anisotropy);
ax = max(Alpha / K, 0.001f);
ay = max(Alpha * K, 0.001f);
#endif
}

Unity的HDRP使用Kulla 2017:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 2021.3.11f1c2\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.render-pipelines.core\ShaderLibrary\CommonMaterial.hlsl

real PerceptualRoughnessToRoughness(real perceptualRoughness)
{
return perceptualRoughness * perceptualRoughness;
}

void ConvertValueAnisotropyToValueTB(real value, real anisotropy, out real valueT, out real valueB)
{
// Use the parametrization of Sony Imageworks.
// Ref: Revisiting Physically Based Shading at Imageworks, p. 15.
valueT = value * (1 + anisotropy);
valueB = value * (1 - anisotropy);
}

void ConvertAnisotropyToRoughness(real perceptualRoughness, real anisotropy, out real roughnessT, out real roughnessB)
{
real roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
ConvertValueAnisotropyToValueTB(roughness, anisotropy, roughnessT, roughnessB);
}

specular anisotropic实现
https://reddish.fun/posts/Article/specular-anisotropy/
作者
bit704
发布于
2024年1月18日
许可协议