안녕하세요 풍풍풍 입니다 (퐁퐁퐁 아닙니다 __)
티스토리도 당연히 되는줄 알고 네이버에서 작업하고 여기다 올렸더니
Xbox가 뜨는 대 참사가 있었네요 __)
오늘 알아 볼 것은 Ashikhmin-Shirley 조명 모델입니다
Satin이나 Velvet에 적합한 조명모델이라고 합니다.
개념. |
Ashikhmin-Shirley 조명 모델이란
Michael Ashikhmin 과 Peter ShirleyCook-Torrance 모델과 마찬가지로 물리적으로 정확한 반사율을 얻기 위하여 프레넬 가중치를 선택하고 있습니다.
아래는 이방성 파라미터(Nu, Nv)에 변화에 따른 조명모델의 효과를 애니메이션으로 나타낸 것입니다
들어가기 전에 BRDF란 용어가 자주 나오는데 간단하게 BRDF가 무엇인지 알아 보겠습니다
Bidirectional Reflectance Distribution Funtion의 약자로 양방향 반사 분포 함수를 말합니다
Surface에 상태에 따른 반사율을 구하는 함수입니다
공식. |
이번 조명은 다음과 같은 식에 의해 만들어집니다
다시 본론으로 가서...
하나하나 풀어 갑니다..
----------------------------------------------------------------------------------------------------------------------------------------------------------
일단 위에 그림에서 최종공식은 간단하게 다음과 같이 표현할 수 있습니다
어렵게 생각 할 필요 없이 Diffuse + Specular 라고 보시면 되겠습니다.
여기서 pd와 ps는 다음과 같은 공식이 됩니다
각 파라미터는 아래와 같습니다
Rd | 디퓨즈 컬러 |
Rs | 일반 입사에 따른 스펙큘러 |
Nu, Nv | 스펙큘러의 모양을 제어하기 위한 지수. Nu=Nv일때는 등방성 하이라이트가 된다 |
위에서 본 공식하고는 다소 틀린데 위 그림은 Steigleder 과 McCool의 구현의 형태를 띄고 있습니다
연산 방식만 틀릴 뿐 내부적으로는 같습니다 __)
결과적으로 P = Pd + Ps 의 형태를 지니고 있는것입니다. 이해하기 쉽도록 참조 용으로 보세요~
차근 차근 살펴 보겠습니다.
Ps 부터 살펴 봅니다
Ps 는 기본모델을 Phong 모델로 잡습니다
이 때, n은 면의 거칠기를 나타냅니다.
이 때, BRDF의 정의를 하기위한 공식에서
(자세한 부분은 리얼타임 렌더링 2판 6장 3절에 BRDF이론을 보시면 됩니다 @_@)
이 때의 Ps는 BRDF가 갖춰야 할 Helmholtz 호환성을 만족하지 않습니다
(Helmholtz reciprocity) :입사각과 반사각은 바뀔 수 있으며 함수 값은 동일하다) |
László Neumann &Attila Neumann 은 이러한 조건을 만족 시키는 BRDF를 제안했는데
맨끝에 F는 프레넬 가중치이며 이때 사용하는 공식은 Schilck의 프레넬 근사치가 사용되었고
여기에 (Half · Normal)위에 있는 n 부분을
이등방성 파라미터로 확장하고
Specular를 구한것이 Ashikhmin-Shirley 조명 모델의 Specular 성분 입니다
Pd (Diffuse에 관한 식) 계산은 BRDF에 Diffuse 공식
으로부터 Diffuse 와 R의계수를 구하여 다음과 같은식을 이끌어 냅니다
성능 개선이 필요할 경우는 위의 식 대신 일반 램버트 방정식을 사용하는 것도 좋은 방식입니다
구현 |
이 공식에서는 cos, sin을 제거하기 위해 GPU 친화적인 내적 연산을 사용한 약간 수정된 공식을 사용합니다.
Ps에서 요구되는 Nu, Nv 벡터는 Tangent Vector 와 BiTangent Vector 이며,
픽셀 셰이더에서는 (1,0,0) 이나 (0,1,0)으로 방정식을 단순화 할수는 있지만,
가능한 그렇게 하지 않는 것이 좋습니다
이를 HLSL로 표현해 보겠습니다
float4 psAshikhminShirley ( in VS_OUTPUT f ) : SV_TARGET { // 보간된 입력값 과 정규화된 상수 파라미터 float3 n = normalize( f.normal ); float3 l = normalize( -vLightDirection ); float3 v = normalize( pCameraPosition - f.world ); float3 h = normalize( l + v ); // 좌표 프레임 선언 float3 epsilon = float3( 1.0f, 0.0f, 0.0f ); float3 tangent = normalize( cross( n, epsilon ) ); float3 bitangent = normalize( cross( n, tangent ) ); // 계산하기 쉽게 몇가지 변수를 미리 생성한다 float VdotN = dot( v, n ); float LdotN = dot( l, n ); float HdotN = dot( h, n ); float HdotL = dot( h, l ); float HdotT = dot( h, tangent ); float HdotB = dot( h, bitangent ); float3 Rd = cDiffuse; float3 Rs = 0.3f; float Nu = fAnisotropy.x; float Nv = fAnisotropy.y; // 디퓨즈 계산 float3 Pd = (28.0f * Rd) / ( 23.0f * 3.14159f ); Pd *= (1.0f - Rs); Pd *= (1.0f - pow(1.0f - (LdotN / 2.0f), 5.0f)); Pd *= (1.0f - pow(1.0f - (VdotN / 2.0f), 5.0f)); // 스펙큘러 계산 float ps_num_exp = Nu * HdotT * HdotT + Nv * HdotB * HdotB; ps_num_exp /= (1.0f - HdotN * HdotN); float Ps_num = sqrt( (Nu + 1) * (Nv + 1) ); Ps_num *= pow( HdotN, ps_num_exp ); float Ps_den = 8.0f * 3.14159f * HdotL; Ps_den *= max( LdotN, VdotN ); float3 Ps = Rs * (Ps_num / Ps_den); Ps *= ( Rs + (1.0f - Rs) * pow( 1.0f - HdotL, 5.0f ) ); // 최종 값 출력
return float4( Pd + Ps, 1.0f ); }
Oren-Nayer 때도 설명했지만 역시 마찬가지로
종속 되는 부분을 찾아 텍스처 룩업을 통해 처리가 가능하지만 일부 작업들 중에는
보틀넥의 주요 원인이 된다는 점 잊지 마세요~
구현은 위의 파일을 다운받아 역시 렌더몽키로 돌리시면 됩니다.
이방성 파라미터인 u와 v (구현 파일 내에서는 fAnisotropy의 x,y 값이 u,v 입니다)의 값들을
조절 하시면 되겠습니다 밑의 예에서는 PI값을 1.0으로 주었을때 입니다
Nu가 커질수록 윤곽을 따라 수평 하이라이트를 보여주며
Nv가 커질 수록 수직 하이라이트를 보여주는 반면
100,100일때는 등방성 분포를 보여주고 있습니다 @_@
여기까지 보시느라 수고 하셨구요
더 알고 싶으신 분은 적당한 구글링을 해주시면 쉽게 찾으실 수 있습니다.. 도망__)
Reference: http://www.cs.utah.edu/~shirley/papers/facets.pdf
http://www.t-pot.com/program/81_Ashikhmin/index.html
http://azzrael.wo.to/study/graphic3d/illumi/phyillum1.htm
http://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function
http://mathinfo.ens.univ-reims.fr/IMG/pdf/A_new_class_of_BRDF_models_with_Fast_importance_sampling_-_Neumann.pdf
'프로그래밍' 카테고리의 다른 글
표준 rand()함수보다 유용한 랜덤 생성 알고리즘 – MT, WELL (23) | 2012.02.27 |
---|---|
D3D에 익숙한 개발자을 위한 OpenGLES 개발 소개 (16) | 2012.02.26 |
Implement Hash String ID Index #2 (4) | 2012.02.21 |
UMDH로 메모리 릭 제거하기. (7) | 2012.02.17 |
게임 오브젝트 설계.. 나도 잘하고 싶다! #2 (13) | 2012.02.17 |