블로그 이미지
자신의 단점을 메꾸는 것을 단(鍛)이라 하고 자신의 강점을 갈고 닦는 것을 련(鍊)이라 하여, 두가지를 합친 것을 단련이라고 부른다. 붕대마음

카테고리

전체목록 (667)
참고사이트 (8)
Goal (4)
Travel (10)
My Life (105)
Game (35)
Game Review (7)
Game Plan (0)
Books (5)
English (1)
Optimizing (12)
Study (218)
유용한 것들_etc (44)
유용한 것들_func (20)
Unity (48)
Unreal (87)
작업장 (54)
RenderMonkey (6)
정리요망 (1)
따라잡기 시리즈 (0)
링크용 (0)
Total344,974
Today26
Yesterday53

'렌더몽키'에 해당되는 글 1건

  1. 2013.01.31 lambert (3)

lambert

RenderMonkey / 2013. 1. 31. 16:11

렘버트 또는 람베르트의 기본 공식은 dot(L,N).
http://mgun.tistory.com/1306
위 링크에서 엄청나게 마니 언급되었던 기본 조명모델이다.
이걸 렌더몽키에서 표현하는것도 무척 쉽다.

공식대로 계산을 하기 위해 Light Vector가 우선 필요하다.





사진으로 보니 더욱 명확하다.
램버트에 대한 내용이나 코사인 각도가 무었을 의미하는지 등은 언급한 링크에서 읽어보면 될 것 같고..
내가 말하고자 하는 것은 벡터의 방향이다.

이 부분에 대한 링크 : http://kblog.popekim.com/2011/01/blog-post_4153.html

첫번째 사진이나 두번째 사진이나 결국은 같은 거라고 생각한다.
내적의 특성상 두번째 사진의 개념은 부호를 한번 뒤집어서 벡터의 방향을 바꿔야 하긴 하지만
개인적인 생각으로는 두번째 사진이 "내가 보기에는" 이해하기가 쉽다.
옆 노멀벡터는 점이 속한 평면에서 수직인 벡터인데 결국 점을 기준으로 방향을 잡기 때문에
광원벡터 역시 광원에서 빛을 쏘는 방향이라고 일관성 있게 이해하고 싶다.


벡터에 대한 정리는 이 링크를 참고하세요. http://mgun.tistory.com/1143

무튼 라이트 위치를 추가해 주자


대략 오른쪽 위에, 모니터의 반대방향쪽에 위치시켰다.


오옷~! 빛의 위치는 바로 저기~!.. 2d 이미지라서 z위치는 식별하기 어렵지만..대략 저기임....

자~ 이제 노말은 어쩔거임? 노말은 이미 시멘틱이 존재한다.
그래서 걍 코딩으로 추가해 주면 된다.
struct VS_INPUT
{
   float4 mPosition : POSITION0;
   float3 mNormal : NORMAL;
};

이제 빛의 위치로 부터 빛의 방향벡터도 가져와야 겠지.
float3 lightDir = Output.mPosition.xyz - gWorldLightPosition;
lightDir = normalize(lightDir);
대부분 알고있겠지만 Position - LightPosition과 LightPosition - Position의 차이는 명백하다.
사실 무었을 하든 상관없다. 이 감산연산의 결과만 제대로 이해하고 있다면.
첫번째 식인 정점의 위치 P에서 광원의 위치 LP를 빼면 LP 에서 P로 향하는 벡터가 만들어 진다.
반대로 LP - P라면 정점 P에서 광원 LP로 향하는 벡터가 만들어 진다.
벡터는 크기와 방향을 가지기 때문에 이 방향을 제대로 아는 것이 상당히 중요하다.

float3 lightDir = Output.mPosition.xyz - gWorldLightPosition;
lightDir = normalize(lightDir);
이 식대로 계산하면 LP에서 P로 향하는 Light Vector을 만들 수 있다.
L(빛의방향 벡터)와 N을 내적해야 하는데 그러기 위해서는 두 벡터의 밑동이 서로 만나야 한다.
하지만 현재 L은 방향이 반대다. 즉 밑동이 광원의 위치이고 머리가 정점의 위치다.

Output.mDiffuse = dot(-lightDir, worldNormal);
그래서 이렇게 내적시 -을 곱해주어 방향을 바꾼다.

그리고 가끔 빼먹는 저 normalize !!.
욘석은 은근히 많은 사람들이 "그냥 올바른 값을 만들기 위한 초기화"정도로 이해하고 있는사람이 많지만
사실 내적의 공식을 들여다보면 반드시 필요한 "정리"다.
내적공식인 dot(A,B) = Cos각도 * A의 길이 * B의 길이로 정리할 수 있는데 두 벡터인 A와 B의 길이를 1로 만들어 주면
dot(A,B) = Cos 각도가 되서 단지 A벡터와 B의 벡터의 내적만으로 간단히 cos의 각도를 구할수 있다는 것이 핵심!
저 normalize가 바로 벡터의 길이를 1로 만들어 주는 정규화를 해 주는 녀석이다.
벡터의 길이가 1인 벡터를 단위벡터라고 말하는데 단위벡터를 직접 구하는건 그다지 어렵지 않다.
단위벡터 = 벡터 / 벡터의 길이.
즉 (1,2,3)의 벡터가 있다면 이 벡터의 길이는 sqrt(1*1 + 2*2 + 3*3) 가 되고
단위벡터는 (1,2,3) / sqrt(14) 가 된다.
사실 여기까진 몰라도 된다. 다만 내가 내가 무의식적으로 적어주는, 또는 빼 먹는 저 normalize가
결코 가볍지 않은 일을 한다는 것을 말하고 싶었다.

추가적으로...
 

half lambert
Output.mDiffuse = pow(dot(-lightDir, worldNormal) * 0.5 + 0.5, 4);


wrapped diffuse

float magicNmuber = 0.5; 
Output.mDiffuse = (dot(-lightDir, worldNormal) + magicNmuber) / (magicNmuber+1);

energy conserving wrapped diffuse
float magicNmuber = 0.5;  
float NdotN = dot(-lightDir,worldNormal);
Diffuse = saturate( (NdotN+magicNmuber) / ((magicNmuber+1)*(magicNmuber+1))); 


렌더몽키 파일 : 


 

'RenderMonkey' 카테고리의 다른 글

Shadow Mapping  (0) 2014.01.11
fresnel  (0) 2013.10.22
normal mapping (법선 매핑)  (2) 2013.02.07
기본적인 반사 벡터  (0) 2013.02.02
lambert  (3) 2013.01.31
흐음...렌더몽키라..  (0) 2013.01.29
Posted by 붕대마음

댓글을 달아 주세요

  1. 2013.02.13 11:49 김성준  댓글주소  수정/삭제  댓글쓰기

    자세한 설명 감사합니다~^^ 한가지 어리석은 질문을 드리겠습니다. 포프님의 책에서도 LightVector를 구하기위해 정점의위치(VP) - 라이트위치(LP) 로 해주고, 나중에 내적을 구할때 -Lightvector 이런식으로 "-"를 붙이는데, 이런식으로 하지않고, LP - VP 로하고 dot(LightVector, worldNormal) 이런식으로 하면 안되는것일까요?

    • 2013.02.13 16:19 신고 붕대마음  댓글주소  수정/삭제

      상관없습니다. 나중에 내적연산할 때만 제대로 설정해 주면 됩니다.
      벡터는 점A - 점B 라고 하면 이 벡터의 방향은 점B에서 점A로 향하는 벡터가 됩니다. 내적연산할 때 인자로 넣어주는 벡터가 어느방향인지만 알고 제대로 넣어준다면 상관없습니다. 벡터 내적시 벡터의 방향이
      왜 중요한지는 내적공식을 보면 알 수 있습니다.
      참고로 렌더몽키나 UDK가 깔려있으시다면 한번 테스트 해 보세요.
      렌더몽키 파일은 올려두었습니다.

  2. 2013.02.13 17:40 김성준  댓글주소  수정/삭제  댓글쓰기

    아~ 그렇군요 감사합니다~^^

최근에 달린 댓글

최근에 받은 트랙백

글 보관함