꽃미남 프로그래머 김포프가 창립한 탑 프로그래머 양성 교육 기관 POCU 아카데미 오픈!
절찬리에 수강생 모집 중!
프로그래밍 언어 입문서가 아닌 프로그래밍 기초 개념 입문서
문과생, 비전공자를 위한 프로그래밍 입문책입니다.
jobGuid 꽃미남 프로그래머 "Pope Kim"님의 이론이나 수학에 치우치지 않고 실무에 곧바로 쓸 수 있는 실용적인 셰이더 프로그래밍 입문서 #겁나친절 jobGuid "1판의내용"에 "새로바뀐북미게임업계분위기"와 "비자관련정보", "1판을 기반으로 북미취업에 성공하신 분들의 생생한 경험담"을 담았습니다.
Posted by 풍풍풍

안녕하세요 풍풍풍 입니다 (퐁퐁퐁 아닙니다 __)

티스토리도 당연히 되는줄 알고 네이버에서 작업하고 여기다 올렸더니 
Xbox가 뜨는 대 참사가 있었네요 __)

조심하겠습니다..__)

오늘 알아 볼 것은 Ashikhmin-Shirley 조명 모델입니다

Satin이나 Velvet에 적합한 조명모델이라고 합니다.

    Satin
 

Velvet



 개념.

 

Ashikhmin-Shirley 조명 모델이란

Michael Ashikhmin 과   Peter Shirley
가 2000년에  "An Anisotropic Phong BRDF Model", Michael Ashikhmin Peter Shirley  논문에서 발표한 모델입니다

Cook-Torrance 모델과 마찬가지로 물리적으로 정확한 반사율을 얻기 위하여 프레넬 가중치를 선택하고 있습니다.



아래는 이방성 파라미터(Nu, Nv)에 변화에 따른 조명모델의 효과를 애니메이션으로 나타낸 것입니다
 


두개의 이방성 파라미터를 조절하여 Velvet 과 Satin의 느낌이 나온다고 보시면 되겠습니다@_@

 들어가기 전에 BRDF란 용어가 자주 나오는데 간단하게 BRDF가 무엇인지 알아 보겠습니다

Bidirectional Reflectance Distribution Funtion의 약자로 양방향 반사 분포 함수를 말합니다
Surface에 상태에 따른 반사율을 구하는 함수입니다
 


 

 공식.

  이번 조명은 다음과 같은 식에 의해 만들어집니다

 간단하죠^_^
죄송합니다 __) 웃길 줄 알았어요...




다시 본론으로 가서...

 

Ashikhmin-Shirley 조명 모델의 공식의 최종 모델은 다음과 같습니다


하나하나 풀어 갑니다..

----------------------------------------------------------------------------------------------------------------------------------------------------------

일단 위에 그림에서 최종공식은 간단하게 다음과 같이 표현할 수 있습니다


 

어렵게 생각 할 필요 없이 Diffuse + Specular 라고 보시면 되겠습니다.

여기서 pd와 ps는 다음과 같은 공식이 됩니다




각 파라미터는 아래와 같습니다

Rd 디퓨즈 컬러
Rs 일반 입사에 따른 스펙큘러
Nu, Nv 스펙큘러의 모양을 제어하기 위한 지수. Nu=Nv일때는 등방성 하이라이트가 된다

과정은 다음과 같이 되겠습니다 @_@ ( 뭔가 저번 포스팅하고 비슷하군요-.-)
위에서 본 공식하고는 다소 틀린데 위 그림은 
Steigleder 과 McCool의 구현의 형태를 띄고 있습니다
연산 방식만 틀릴 뿐 내부적으로는 같습니다 __)
결과적으로 P = Pd + Ps 의 형태를 지니고 있는것입니다. 이해하기 쉽도록 참조 용으로 보세요~

차근 차근 살펴 보겠습니다.

Ps 부터 살펴 봅니다

Ps 는 기본모델을 Phong 모델로 잡습니다


이 때, n은 면의 거칠기를 나타냅니다.

이 때, BRDF의 정의를 하기위한 공식에서


입사 방향에 Cosine 각이 들어가므로 이 항을 상쇄 하기 위해 (n·l)로 나누어 줍니다
(자세한 부분은 리얼타임 렌더링 2판 6장 3절에 BRDF이론을 보시면 됩니다 @_@) 


이 때의 Ps는 BRDF가 갖춰야 할 
Helmholtz 호환성을 만족하지 않습니다
(Helmholtz reciprocity)  :입사각과 반사각은 바뀔 수 있으며 함수 값은 동일하다)   

László Neumann &Attila Neumann 은 이러한 조건을 만족 시키는 BRDF를 제안했는데
그 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 = 10 , Nv = 5000

Nu = 100, Nv = 100
 

Nu = 5000, Nv = 10
 

Nu = 5000 , Nv = 5000


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   
TAG

댓글을 달아 주세요

  1. Hybrid 2012.02.26 18:48  댓글주소  수정/삭제  댓글쓰기

    오오~ 글 잘봤습니다.
    리플 안달려고 하다가, 레퍼런스 목록이 존재하는 것을 보고 감동 받고(?) 리플 답니다ㅋ

  2. Favicon of https://gamedevforever.com zinzza 2012.02.26 19:52 신고  댓글주소  수정/삭제  댓글쓰기

    이번 조명은 다음과 같은 식에 의해 만들어집니다
    이후 정신이 멍해져서...ㅡ.ㅡ

    늘 화이팅입니다
    까지 휘뤼뤽~ 하고 휠을 굴렸어요... 죄송합니다 ㅜㅜ

  3. Favicon of https://gamedevforever.com 대마왕J 2012.02.26 23:59 신고  댓글주소  수정/삭제  댓글쓰기

    ㄷㄷㄷ 저 조명은 예전에 제가 다른 글 보면서 따라 만들어 놓고도 어라 어떻게 만든거지? 라고 했던 그 조명!!! 담에 필요하면 이거 보고 꼭 만들어 봐야지!! 이번엔 제대로!!! 감사합니다!!!

  4. Favicon of https://gamedevforever.com 김포프 2012.02.27 05:44 신고  댓글주소  수정/삭제  댓글쓰기

    머리카락에도 쓸수 있을까요...?

    • Favicon of https://gamedevforever.com 대마왕J 2012.02.27 09:20 신고  댓글주소  수정/삭제

      머리카락에 보통 쓰지요. 저도 써 봤는데, 애석하게도 UV를 똑바로 펴야만 하더라고요. 아티스트들은 근데 머리를 굉장히 자유자재로 쓰고 싶어해서 포기.

  5. Favicon of https://gamedevforever.com 김포프 2012.02.28 15:30 신고  댓글주소  수정/삭제  댓글쓰기

    참 풍풍풍님 잘 낚아왔다.... 라는 생각을 합니다.. (한편으로는 난 머하는거지? 하는 생각도 ㅎㅎ -_-;) 계속 좋은 글 기대할께요~