주의 : 잘못된 내용이 포함되어 있을 수 있으므로 이상하면 참고자료를 확인하세요.
주의 : 여기에서 Specular BRDF 공식에 대해서는 자세하게 다루지 않을 계획입니다. 공부를 더 하고 싶은 분들은 참고자료들을 확인하세요.
[ PBR 이란 무엇인가 ] 20. Specular BRDF
[ 19. Diffuse BRDF ] 에서 Diffuse 를 위해서는 일괄적으로 Lambert cosine law 를 사용한다고 했습니다. 그렇기 때문에 금속이 아니라면 Diffuse 는 모든 재질에 대해서 동일하게 적용된다고 보면 됩니다.
Disney 의 Burley 같은 경우에는 새로운 diffuse model 을 만들었습니다. 그러나 그것은 그림1 처럼 외형상 큰 차이를 보여주지 못하고 계산 비용만 더 들기 때문에 실시간 그래픽스에서 잘 사용되지 않습니다.
그림1. Lambert 모델과 Burley 모델의 비교. 큰 차이를 보이지는 않음. 출처 : [ 1 ].
하지만 Specular 의 경우는 다릅니다. 물체가 어떤 재질로 구성되어 있느냐에 따라 달라집니다( 물론 Diffuse 도 그래야 하지만 대충 넘어갑시다. 두 마리 토끼를 잡기는 쉽지가 않으니... ). Specular 는 물체의 재질특성을 보여주는 매우 중요한 요소입니다. 그러므로 여러분이 한 번이라도 들어 본 대부분의 BRDF 모델들은 거의 다 specular 와 관련된 것일 겁니다. 그렇기 때문에 조금 비용을 들이더라도 재질 차이를 확실하게 보여 줄 만한 모델을 사용하죠.
지금까지 우리는 PBR 의 대원칙들에 대해서 살펴 봤습니다. 처음에 글을 시작하면서 PBR 이라는 것은 다음과 같은 요소를 포함해야 한다고 했습니다.
- 전역 조명( Global Illumination ) : 이미지 기반 라이팅( Image Based Lighting, IBL ).
- 에너지 보존 법칙( Energy Conservation ).
- 반사도( Reflectivity ) : 디퓨즈 및 스펙큘러( Diffuse & Specular ).
- 미세면( Microsurface ) : 러프니스( Roughness ).
- 프레넬 법칙( Fresnel's Law ).
- 금속성( Metalicity ).
[ 1. 인간과 빛 ], [ 2. 조도와 휘도 ], [ 3. 빛의 감쇠 ], [ 4. 광원의 밝기( 광속 ) ], [ 5. 조도( illuminance ) 측정 ], [ 6. 휘도( luminance ) 측정 ] 에서는 빛의 기본 성질에 대해서 중점적으로 이야기했습니다.
[ 7. Light Intensity 설정 ], [ 8. Attenuation Radius 설정 ] 에서는 에너지 보존 법칙에 대해서 중점적으로 이야기했습니다.
[ 9. Global Illumination & Indirect Lighting ], [ 10. Image Based Lighting ], [ 11. UE4 GI : Sky Light ], [ 12. UE4 GI : Reflection Capture ], [ 13. UE4 GI : Lightmass & Mobility ] 에서는 전역 조명에 대해서 중점적으로 이야기했습니다.
[ 14. 모든 것은 빛납니다 ], [ 15. 모든 것은 프레넬을 가집니다 ], [ 17. Fresnel 이란 ] 에서는 프레넬 법칙에 대해서 중점적으로 이야기했습니다.
[ 실제 이미지에서 specular 와 Diffuse 분리하기 ], [ 16. Reflection 에 대한 잘못된 상식들 ], [ 18. Distribution Function ] 에서는 반사도와 Diffuse 및 specular 개념에 대해서 중점적으로 이야기했습니다.
[ 19. Diffuse BRDF ] 에서는 Diffuse BRDF 에 대해서 중점적으로 이야기했습니다.
마지막으로 이번 챕터에서는 미세면과 금속성에 대해서 다루게 됩니다. 아무런 순서도 없이 두서없이 글을 진행한 것처럼 보였을지 모르겠지만 나름대로 생각하고 진행했답니다.
이제 PBR 에서의 specular BRDF 에 대해 중점적으로 살펴 보도록 하겠습니다.
MERL 100
Diffuse 및 Specular 모델을 만들 때 그냥 내키는 대로 만드는 것은 아닙니다. 어떤 기준이 있어야 하며 실제로 측정된 BRDF 모델을 사용하는 경우가 많습니다. 그 중 하나가 MERL 100 이라는 것이죠.
그림2. MERL 100. 출처 : [ 2 ].
이것은 100 개의 등방성 재질을 캡쳐한 것으로 페인트, 나무, 금속, 섬유, 돌, 플라스틱, 그리고 다른 합성 재질들을 포함합니다. 이것은 새로운 BRDF 모델들이 나오면 그것의 결과가 얼마나 맞는지 확인하기 위해서 사용됩니다. 자세한 내용에 대해서 알고자 한다면 [ 2 ] 를 확인하시기 바랍니다.
이 MERL 100 을 반드시 이해하실 필요는 없습니다. 지금 우리가 다루고 있는 영역이 매우 물리적인 측정값에 기반하고 있다는 것을 강조하기 위해서 언급했을 뿐입니다.
미세면 분포 함수 : D 함수
미세면( Microfacet ) 모델이라는 것은 폴리곤의 거대면( Mcrosurface )은 그림3 처럼 미세면으로 구성되어 있다는 전제에서 반사나 굴절을 모델링하는 것을 의미합니다.
그림3. Microsurface vs Macrosurface. 출처 : [ 4 ].
여러분은 반짝반짝 빛나는 면들은 매끈하고 빛나지 않는 면들은 거칠다는 것을 경험적으로 알고 계실 겁니다. 물론 코팅을 해 놓아서 빛날 수도 있지만 그 부분은 예외로 두고 이야기하도록 하겠습니다.
하지만 이러한 미세면의 분포는 재질마다 다를 겁니다. 그것을 Albedo 설정하듯이 아티스트가 일일이 설정할 수는 없겠죠. 게다가 미세면이라는 것은 거의 눈에 보이지도 않는 면을 이야기합니다.
그러므로 몇 가지 매개변수만으로 분포를 계산할 수 있는 함수가 필요하겠죠? 그것이 바로 미세면 분포 함수입니다. Distribution 의 머리글자를 사용해 이 함수를 D 라고 부릅니다. 일반적으로 이 D 함수는 통계적인 기법을 이용하게 됩니다. 여기에서 세부 사항에 대해서 구체적으로 다루지는 않겠습니다. 더 구체적으로 알고 싶은 분들은 참고자료를 확인하세요.
어쨌든 이 D 함수는 Specular Peak 가 어느 방향을 향하게 되는지를 결정하게 됩니다. 우리는 Specular 를 거울면 반사라고 생각하고 있지만, 사실은 입사각과 반사각이 정확하지는 않습니다. 이는 표면의 거칠기( 미세면의 분포 )에 영향을 받게 되죠. 거울면 반사에서 벗어나서 생기는 반사를 "Off-specular reflection" 이라고 부릅니다. 우리 말로 굳이 해석하자면 "거울면 반사( 정반사 )를 벗어난 반사"라고 할 수 있겠습니다.
그림4 는 서로 다른 미세면 분포를 가진 표면에서 이 off-specular reflection 이 어떻게 달라지는 지 보여 줍니다.
그림4. Off-specular reflection 의 예: 지표각에 가까워질 수록 specular 의 방향( M ) 이 반사각과 달라지는 모습을 보여줌.
즉 D 함수는 거대면 내에서 우리에게 거울면 반사를 보여줄 수 있는 미세면의 양이 얼마나 되는지를 알려주는 것입니다( 여기에 대해서 제가 이해한 바를 정리해 봤는데, 자세히 알고 싶으신 분들은 [ PBR Specular D 의 기하학적 의미 ] 를 참고하세요 ).
미세면 그림자 마스킹 함수 : G 함수
자, 여러분은 렌더링할 때 그림자가 없으면 매우 어색하다는 것을 알수 있습니다. 미세면의 그림자의 경우에는 그 정도 영향력을 가지지는 않습니다. 눈에 거의 보이지도 않는데 알게 뭡니까.
그림5. 그림자 마스킹의 기하학. 같은 미세면 노멀 m 을 사용하는 세 지점을 비교.
두 개는 i 와 o 방향에서 보이며, 한 개는 i 방향에서 차폐됨.
하지만! 에너지 보존 법칙을 위해서는 반드시 고려되어야 합니다. 그런데 미세면 그림자 마스킹도 아티스트가 작업할 수 있을만한 건 아니겠죠. 그래서 이것도 함수로 만듭니다. 기하와 관련된 것이므로 Geometry 의 머리글자를 사용해 G 함수라고 부릅니다.
프레넬 함수 : F 함수
모든 물체의 반사에는 프레넬 법칙이 적용된다고 했습니다. 그러므로 당연히 이것과 관련한 함수도 있겠죠? Fresnel 의 머리글자를 사용해 F 함수라고 부릅니다. 프레넬이 뭔지 기억이 가물가물한 분들은 [ 17. Fresnel 이란 ] 을 참고하세요.
금속일수록 거의 거의 대부분의 각도에서 높은 반사율을 보이며, 비금속일수록 지표각에서 높은 반사율을 가집니다.
모아봅시다
자 위에서 언급한 세 개의 함수를 모아 봅시다. 어떤 빛이 표면에 들어 오면 미세면 분포 함수 D 에 의해서 off-specular reflection 이 결정될 것이고, 기하학적 감쇠 G 함수에 의해 에너지 보존 법칙이 적용됩니다. 그리고 프레넬 함수 F 에 의해 반사율이 결정됩니다.
눈치가 빠른 분들은 D 와 G 가 표면의 거칠기( roughness )와 관련이 있고 F 가 금속성( metallicty )과 관련이 있음을 알 수 있을 겁니다. 이걸 제대로 표현하기 위해서는 매우 많은 공식이 필요하지만 여기에서는 구체적으로 언급하지 않겠습니다. 참고자료를 확인하시기 바랍니다.
그러므로 미세면과 프레넬을 고려한 Specular BRDF 는 기본적으로 식1 과 같은 형태를 띄고 있습니다. 우리가 위에서 언급하지 않은 것들이 분모에 들어 가 있지만 별로 신경쓰실 것은 없습니다. 빛과 표면의 관계 및 에너지 보존을 위해 들어 가 있습니다 :
식1. Specular BRDF.
식1 은 Cook-Torrance 의 BRDF 모델이며, D, F, G 를 위해 어떤 알고리즘을 사용하느냐에 따라 결과가 조금씩 달라집니다. UE4 의 경우에는 D 를 위해 GGX 를, G 를 위해 Smith Approximation 을, F 를 위해 Shilick's approximation 을 사용합니다. 여러 가지 변종들에 대해서 궁금하다면, Graphic Rants 블로그의 [ Specular BRDF Reference ] 를 참조하세요.
여기에서 식을 언급하기는 했지만 굳이 이해하실 필요는 없습니다. 위에서 언급했듯이 roughness 값은 D 와 G 에 영향을 주고, metallic 값은 F 에 영향을 준다는 것만 알고 계시면 됩니다.
Roughness 는 반사의 선명도 및 확산과 관련이 있으며, metallic 은 반사의 세기 및 각도와 관련이 있습니다.
UE4 에서 Metallic
UE4 에서의 Metallic 에 대해서 이야기해 보도록 하겠습니다. 이것은 프레넬과 관련이 있다고 했습니다. 정확하게 말하자면 F0 값입니다. 굴절률( Index Of Refraction, IOR ) 값으로부터 결정됩니다. 이에 대해서는 [ 17. Fresnel 이란 ] 에 자세히 언급했으니 기억이 안 나면 참고하세요. 앞의 링크에는 IOR 을 F0 로 변경하는 공식과 IOR 정보를 알 수 있는 사이트에 대한 링크가 있습니다.
그림6. 프레넬 공식 그래프. 출처 : Real-Time Rendering, 3rd Edition.
금속들은 수직으로 내려다 봤을 때( 즉 0 도일 때 ) 0.5 이상의 F0 값을 가지고 있으며, 보석같은 경우에는 0.2 이하의 F0 의 값을 가지고 있으며, 우리가 자연에서 볼 수 있는 많은 물체들은 0.05 이하의 값을 가지고 있습니다.
낮은 F0 값을 가질 수록 지표각에 가까워져야 반사가 제대로 보입니다. 이 F0 값이 Metallic 값으로 사용됩니다. 즉 높은 metallic 값을 가진다면 아무데서나 봐도 반사가 잘 보이고, 낮은 metallic 값을 가진다면 지표각에 가까워야 반사가 잘 보인다는 의미입니다.
이것의 활용법에 대해서는 아래에서 자세히 다루도록 하겠습니다.
UE4 의 SpecularColor
그런데 여기에서 하나 알고 넘어 가야 할 것이 있습니다. UE4 에서의 SpecularColor 의 개념입니다. 원래 SpecularColor 라는 것은 재질의 색상이 아니라 빛의 색상을 의미해야만 합니다. 하지만 완벽하게 Metallic 이 0 이거나 1 인 경우는 거의 없기 때문에 이 색상이 섞이게 됩니다. 그리고 전에 말씀드렸듯이 금속은 모든 빛을 흡수해서 방출하기 때문에 Diffuse 가 존재하지 않고 Specular 는 금속 특유의 색상이 나오게 됩니다. 그런데 SpecularColor 핀을 추가하는 것은 ( 성능 및 메모리에 ) 부담이 되므로 BaseColor 를 마치 금속 특유의 방출 색상인 것처럼 사용하게 됩니다.
이를 위해 UE4 는 다음과 같이 SpecularColor 와 DiffuseColor 를 적용합니다.
SpecularColor = lerp( 0.08 * Specular.xxx, BaseColor, Metallic.xxx ); |
공식이 어려워 보이겠지만 잘 생각해 보면 그렇게 어렵지는 않습니다. 먼저 SpecularColor 를 결정하는 공식을 보죠. lerp( x, y, z ) 는 x 와 y 값을 z 값으로 선형보간합니다. 알파블렌딩과 유사하다고 보시면 됩니다. z 가 0 이면 x 값이 1 이면 y 값이 나오는 것이죠.
만약 완전한 금속( Metallic = 1 )이라면 BaseColor 를 사용하고, 완전한 비금속( Metallic = 0 )이라면 0.08 * SpecularColor.xxx 를 사용합니다. 여기에서 xxx 라는 것은 rgb 각 채널에 한 값을 반복해서 넣겠다는 의미입니다. 즉 값이 vector 가 아니라 scalar 라는 의미죠. 저 SpecularColor 라는 것은 material node 에 존재하는 "Specular" 핀을 의미합니다.
그림7. Material Specular 핀.
어떤 분들은 여기에다가 Color 를 넣는 경우가 있는데, 핀 이름이 "Specular Color" 가 아니라 "Specular" 인 이유가 있습니다. 이 경우에는 scalar 값이므로 Color 를 넣어도 의미가 없습니다. 만약 color 를 넣게 된다면 R 채널만을 사용하게 됩니다.
그림8. 잘못된 Specular 값 설정. 이 경우에는 R 채널값이 0.839 가 사용됨.
자 이제 다시 본론으로 돌아와서 Specular 값에 0.08 이 곱해져 있으므로 이건 상당히 미세한 값을 의미합니다. Specular 를 설정하지 않으면 기본값이 0.5 이므로 실제로는 0.04 의 값이죠. 다시 말해 Metallic 이 0 이어도 specular 가 0.4 정도의 비율로 반영된다는 의미입니다.
SpecularColor 값은 다음과 같이 결정됩니다.
Metallic |
Equation |
Result |
0 |
0.08 * Specular.xxx * ( 1 - 0 ) + BaseColor.xyz * ( 0 ) |
0.08 * Specular.xxx |
0.3 |
0.08 * Specular.xxx * ( 1 - 0.3 ) + BaseColor.xyz * 0.3 |
0.056 * Specular.xxx + 0.3 * BaseColor.xyz |
0.6 |
0.08 * Specular.xxx * ( 1 - 0.6 ) + BaseColor.xyz * 0.6 |
0.032 * Specular.xxx + 0.6 * BaseColor.xyz |
1.0 |
0.08 * Specular.xxx * ( 1 - 1 ) + BaseColor.xyz * 1 |
BaseColor.xyz |
BaseColor 는 RGB 채널을 모두 쓰고 SpecularColor 는 scalar( 즉 회색 ) 입니다. 그래서 Metallic 이 1 에 가까워지면 SpecularColor 의 색상에 BaseColor 가 많이 묻어 나오고, 0 에 가까워지면 BaseColor 의 색상이 덜 묻어 나옵니다. BaseColor 의 색상이 덜 묻어 나온다는 것은 순수한 라이트의 색상에 가깝다는 의미죠. 대신 SpecularColor 에 0.08 이 곱해져 있으므로 specular higthlight 가 약해집니다.
그림9. Metallic 에 따른 specular color. Diffuse 를 off 시킴.
광원이 흰색이라 차이가 잘 안 드러나죠? 보라색 광원을 하나 배치해 보겠습니다.
그림10. 색상이 있는 광원을 추가했을 때의 결과. 순서는 그림 9와 같음. Diffuse 를 off 시킴.
그림10 을 보면 metallic 이 낮을수록 원래 광원의 색상이 더 반영된다는 것을 확실히 알 수 있습니다.
그런데 비금속( metallic 이 0 이 아님 )인 경우에 specular 를 올리거나 내리고 싶은 경우가 있습니다. 이럴때 바로 "Specular" 핀을 사용하는 것입니다. 그러면 그림11 과 같은 결과가 나옵니다.
그림11. Metallic = 0 일때 Specular 설정 결과 비교. Diffuse 를 off 시킴.
만약 비금속재질에서 반사에 라이트 색상을 보존하고 싶으시다면 SpecularColor 를 구하는 공식을 프로그래머에게 변경해 달라고 요청하시면 됩니다.
UE4 의 Roughness
아마 roughness 는 ( 눈으로 보기에 ) 가장 이해하기 쉬운 개념일 것입니다. 물론 내부적으로는 D 와 G 를 위해서도 사용되기는 하지만 별로 신경을 쓸 필요는 없겠죠.
그냥 아티스트 입장에서는 "거칠면 반사가 뭉개지고 안 거칠면 반사가 또렷해진다" 정도로 이해하면 그만이겠습니다.
그림12. Metallic 이 0.5 일때 Roughness 변화에 의한 결과. Diffuse 를 off 시킴.
에너지 보존 법칙
위에서 specular G 에 대해 언급하면서 에너지 보존 법칙을 이야기했습니다. 하지만 여기에서는 Diffuse 와 Specular 의 관계에 있어서 에너지 보존 법칙을 이야기하고자 합니다.
표면에 들어 온 빛은 일부는 흡수되고, 일부는 반사되고, 일부는 투과됩니다. 이 반사되는 빛은 Diffuse 와 Specular 로 나뉜다는 것은 익히 알고들 계실 겁니다. 그런데 문제는 Diffuse 와 Specular 가 어느 비율로 반사되느냐입니다. 예전 Phong 과 같은 모델에서는 그냥 아티스트가 임의로 설정하게 했습니다. Kd 나 Ks 같은 항이 있었죠. 아티스트가 원하는 결과를 만들려고 하다 보니 과도한 라이팅이 들어 가는 경우가 많았습니다.
사실 조명에 대한 이해가 높지 않으면 적정 값을 설정하기 힘들죠. 그것도 한씬이 아니라 다양한 라이팅 환경이 존재하는 씬에서 맞추는 것은 쉽지가 않은 일입니다.
그림13. 에너지 보존 적용하지 않은 경우. 가장 왼쪽은 과도하게 빛나고 가장 오른쪽은 선명하지 않음. 출처 : Energy Conservation In Game.
그림14. 에너지 보존 법칙이 적용된 경우. 출처 : Energy Conservation In Game.
하지만 PBR 에서는 들어 온 빛의 양보다 나가는 빛의 양이 많아서는 안 됩니다. 그러므로 흡수되거나 투과되는 빛이 없다고 가정할 때 Diffuse + Specular 의 양은 항상 들어 온 빛의 양과 같아야만 하죠. 그래서 UE4 에서는 Metallic 을 가지고 Diffuse 의 양을 조절합니다.
DiffuseColor = BaseColor - BaseColor * Metallic; |
Metallic 이 세지면 specular 가 세진다는 의미이고 Diffuse 의 양이 줄어들게 됩니다. 위에서 SpecularColor 를 구할 때 lerp 의 파라미터로 Metallic.xxx 를 넘기고 있기 때문에 Metallic 이 크면 Specular 가 늘어나고 Metallic 이 작으면 Diffuse 가 늘어나는 결과를 내게 되는 것입니다.
이것은 기존의 non-PBR 환경의 작업자들에게는 좀 어색하게 느껴질 수 있습니다만, 물리적으로 올바른 결과이고 라이팅 환경이 달라도 어색함이 적어집니다. 게다가 그 비율을 아티스트가 신경쓰지 않아도 되니 금상첨화입니다.
결론
Specular BRDF 공식은 매우 복잡하지만, 아티스트 입장에서는 metallic 과 roughness 만 알면 대충 재질을 설정할 수 있습니다. 그리고 그 재질들을 위한 물리적 값은 이미 정해져 있고 그것을 데이터베이스로 만드는 것이 아티스트나 팀의 역량이 되겠죠.
막말로 metallic 같은 경우에는 비금속은 0 금속은 1 이라고 설정해도 문제될 것은 없습니다. 대부분 roughness 가 중요한 factor 가 됩니다. 그러므로 특이한 경우( 매우 정교하게 섞인 복합재질 )가 아니라면 metallic 을 위해서 큰 리소스를 할당할 이유가 없습니다. 맵이 거의 단색으로 나온다고 해도 과언이 아닙니다. 만약 맵을 따로 만든다면 metallic 과 관련한 맵만 작게 만드는 것도 최적화를 위해 좋을 것입니다.
시리즈를 마무리하며...
Specular BRDF 는 [ PBR 이란 무엇인가 ] 시리즈에서 이야기하고자 하는 최종 보스라 할 수 있습니다. 이제 외전격의 이야기 몇 개만 제외하면 실질적으로 마지막 글이라고 생각하셔도 무방합니다. 이제 대단원( ? )의 막을 내리게 되겠네요. 제대로 이야기를 못 풀어 나간 것 같아서 아쉽기도 하지만, 이제 저작의 고통에서 벗어날 수 있다는 생각에 시원하기도 하네요. 이런 걸 시원섭섭하다고 하죠 ㅋ.
아티스트도 쉽게 이해할 만한 내용을 쓰고 싶었는데 많은 내용을 담으려고 욕심을 내다가 보니 밸런스를 잘 못 맞춘 것 같아서 아쉽네요. 아티스트도 만족을 못하고 프로그래머나 TA 도 만족을 못하는 그런 글이 되지 않았나하고 자평을 해 봅니다.
다음에 기회가 되면 보충글을 더 올리도록 하겠습니다. 지금까지 긴 시리즈를 읽어 주셔서 감사합니다.
추가 : [ 21. PBR 셰이더 구성 ].
참고자료
[ 1 ] Real Shading in Unreal Engine 4, Biran Karis.
[ 2 ] A Reflectance Model for Computer Graphics, Robert L. Cook and Kenneth E. Torrance.
[ 3 ] Physically-Based Shading at Disney, Brent Burley.
[ 4 ] Microfacet Models for Refraction through Rough Surfaces, Bruce Walter, Stephen R. Marschner, Hongsong Li, Kenneth E. Torrance,.
'PBR(Physically Based Rendering)' 카테고리의 다른 글
[ PBR 이란 무엇인가 ] 21. PBR Shader 구성 (22) | 2019.08.03 |
---|---|
[ PBR 이란 무엇인가 ] 19. Diffuse BRDF (2) | 2017.10.15 |
[ PBR 이란 무엇인가 ] 18. Distribution Function (4) | 2017.10.09 |
[ PBR 이란 무엇인가 ] 17. Fresnel 이란? (12) | 2017.09.17 |
[ PBR 이란 무엇인가 ] 16. Reflection 에 대한 잘못된 상식들 (2) | 2017.09.10 |
[ PBR 이란 무엇인가 ] 15. [ 번역 ] 모든 것은 프레넬을 가집니다 (2) | 2017.09.03 |
[ PBR 이란 무엇인가 ] 14. [ 번역 ] 모든 것은 빛납니다 (0) | 2017.09.03 |
[ PBR 이란 무엇인가 ] 13. UE4 GI : Lightmass & Mobility (2) | 2017.08.27 |
[ PBR 이란 무엇인가 ] 12. UE4 GI : Reflection Capture (6) | 2017.08.20 |
[ PBR 이란 무엇인가 ] 11. UE4 GI : Sky Light (4) | 2017.08.01 |