Depth Of Field 1 (Simple DOF)

반응형
Depth Of Field
- 한국어로 피사계 심도(한국어가 더 어려운...)라고 한다.
   원래 사진술 관련 용어로서 한장의 사진에서 초점이 맞은것으로 인식되는 범위.
   즉, 실제 사진에서 초점면을 중심으로 서서히 흐려지는 현상이 발생하는데
   이때 충분히 초점이 맞은것으로 인식되는 범위의 한계를 피사계 심도라고 한다.


  그렇다면 이 DOF(피사계심도, Depth Of Field)에 영향을 주는 것은 어떤것이 있는가?

  1. 조리개 값

      조리개는 간단히 말해 빛의 양을 조절한다.
      렌즈를 통해 카메라로 빛이 유입되는 통로의 폭을 결정하는데 당연히 그 폭이 넓을 수록 보다 많은
      빛이 유입되고, 빛이 많이 유입될 수록 DOF에 미치는 영향력도 커진다.

               조리개값이 작을 수록 DOF가 얇아진다. 위 사진은 작은 조리개값을 사용하여 DOF를 얕게 만들어
               화면 중간 부분만 또렷하게 나오도록 하였다.

      각 조리개값에 따른 DOF의 변화를 보기 원한다면 Wiki를 참고하면 된다.
      http://ko.wikipedia.org/wiki/%ED%94%BC%EC%82%AC%EA%B3%84_%EC%8B%AC%EB%8F%84

      렌즈의 F값은 렌즈의 조리개의 개방정도를 나타내는데 렌즈의 구경/조래개의 개방정도로 표현된다.
      위의 사진을 보면 조리개 값이 작을 수록 DOF가 얇아져서 화면이 많이 뿌옇게 보이는 걸 알 수 있다.

  2. 초점 거리
      초점거리가 길수록 망원에 가까워지는데 망원이라는 것이 곧 무었인가를 확대 한 다는 개념이다.
      따라서 초점이 맞는 부분과 맞지 않는 부분과의 차이도 확대되게 된다.
      망원렌즈 역시 같은 맥락으로 멀리있는 물체 따위를 크고 정확하게 볼 수 있도록 초점 거리를 비교적 길게 만든 렌즈다.    

  3. 카메라와 피사체의 거리
      카메라가 피사체에 가까울 수록 피사체 전면과 후면의 상대적인 거리가 멀어진다.
      이 상대적인 거리가 멀어질 수록 DOF가 얕아지게 된다.

위 사진을 보면 카메라를 책에 가까이 가져가면 뷰 파인더 내에서 볼 때 책 상단의 글씨와
책 하단의 글씨사이의 거리가 상대적으로 멀어지게 된다. 따라서 심도가 얕은, 즉 아웃포커싱이 많이 일어나게 된다.

OK !!
여기까지 정리 해 보자면 Depth Of Field(피사계 심도, DOF)는 렌즈로 어떤 특정한 물체를 볼 때
그 앞/뒤로 초점이 맞는 범위를 이르는 말이다.



그렇다면 초점에서 떨어져 있는 물체는?
이 물체들에게는 초점과의 거리에 따라서 물체가 특정한 무늬 모양으로 흐려지는 현상이 나타난다.
이를 착란원(Circle Of Confusion)이라고 한다.
COC의 크기는 물체의 윤곽선의 해상도에도 영향을 주는데 이 때 COC가 너무 커서 물체의 윤곽을
뚜렷하게 인식할 수 없어지는 범위까지가 DOF이다.

위의 그림을 보면 두번째 그림이 초점이 맞게 나온 것이다.
첫번째 그림은 찍고자 하는 물체보다 초점이 앞에 있어 COC가 생긴다.
세번째 또한 내가 찍고자 하는 물체보다 뒤에 초점이 있어 COC가 생겨 흐릿한 이미지가 나온다.

COC(Circle Of Confusion에 대한 추가설명....


"렌즈에 의해 결상이 되어지는 물체의 한점은 상면에서 점으로 맺혀지지만,
상면의 전 후로 멀어질수록 점이 커져서 원으로 보이게 됩니다.
이것을 착란원이라고 하고 그 크기를 원의 지름으로 표시하는 것입니다.
이 착락원의 크기는 피사계 심도, 초점심도, 과초점거리를 계산하는 기준으로 사용하는 것입니다.
허용 착란원 permissible circle of confusion 또는 허용 분원 circle of confusion 허용 흐림 circle of confusion 이라고도 합니다.
착란원의 지름이 작으면 점으로 인식이 되지만 점이 커지면 점이 원으로 되어 초점이 흐려지게 되는 것입니다.
점으로 인식되는 최대 허용 한계를 허용착란원이라고 하는 것인데, 허용 착란원의 지름은 화면의 대각선이
10inch가 되는 6x8inch 사진을 10inch(약 25.4cm)거리에서 볼 때에 1/100inch로 규정되는 것이 일반적이기는 합니다.
조도나 개인 시력, 콘트라스트, 형태의 지각 능력 등의 요소에서 영향을 받는 편이지만,
이를 무시하고 피사계 심도, 초점심도, 초점거리 등을 계산 할 때에 사용되고 있습니다.
35mm 네거티브의 경우에 네거티브의 크기가 6x8inch 에 비해 길이의 비로 1/6 정도이므로1/100 x1/6 = 1/600inch(약0.04mm)
정도의 길이가 네거티브 상의 허용 착란원의 지름이 되는 것입니다.
일반적으로 화면 대각선의 길이의 1/1000~1/1500 정도로 계산을 하는 편이는 합니다.
사진에서 초점이 맞지 않았을 때에 착란원이 커지게 되면 점이 원으로 나타나게 되는 것입니다."
link : http://k.daum.net/qna/view.html?qid=3kJ12&aid=3kPxv   

핀홀 카메라에 대한 깔끔 설명 http://carstart.tistory.com/179


DOF를 구현해 보자!!


간단하게 말하자면 초점이 맞는 곳은 깔끔하게 나오고 초점이 맞지 않는 곳은 뭉개져서 나온다는 개념이다.
이를 구현하기 위해서 어떻게 해야 할까?
화면의 특정 부위가 뭉개져야 하는지 깔끔하게 나와야 하는지의 기준이 초점이고, 그 초점을 구분 할 수
있는 것은 카메라로부터의 거리값, 즉 깊이값이다.
1. 일반화면 하나를 준비한다.
2. 뭉갠화면 하나를 준비한다.
3. 초점을 기준으로 일반화면과 뭉갠화면을 합성한다.

pass0 - 원본 화면

vs shader
크게 특별한 건 없다.
Out.Position = mul(Input.Position, view_proj_matrix);    position을 투영공간으로 옮겨준다.
Out.TexCoord = Input.TexCoord;

Out.Normal = mul(Input.Normal, view_matrix); normal은 view공간으로 옮긴다.

거리 값을 view공간에서의 position값을 곱한다. ps에서 하는것 보다는 vs에서 하는게 퍼포먼스적으로 낫다.
Out.ViewVec = -distanceScale * mul(Input.Position, view_matrix);

ps shader
float3 base = tex2D(Base, Input.TexCoord);    텍스쳐 픽셀값
float diffuse = dot(lightDir, Input.Normal);         렘버트 diffuse
float specular = pow(saturate(dot(reflect(-normalize(Input.ViewVec),Input.Normal),lightDir)), 16); specular값

float3 light = Kd * diffuse * base + Ks * specular;   최종 light 값

float dist = length(Input.ViewVec);   viewvec의 길이를 구해 거리값으로 사용한다.
return float4(light, dist);  

위의 사진은 그냥 결과화면을 보기 위해 뿌린거고 원래는 렌더타겟에 뿌려줘야 한다.


pass 1 blur

두번째 패스는 블러(뭉개기)다.
이 패스에서는 DOF 이외의 영역에서 흐려지는 부분을 만들어 주기 위해 블러를 사용했다.

vs shader
Pos.xy = sign(Pos.xy);  -1~1사이의 값으로 만들어서 부정확한 부분의 값을 없앤다.


Out.Pos = float4(Pos.xy, 0, 1);    어차피 이 pos값은 텍스처 uv로 쓸거임..

-1~1 사이의 값을 uv에서 허용하는 0~1사이의 값으로 변환시켜준다.
Out.texCoord.x = 0.5 * (1 + Pos.x);
Out.texCoord.y = 0.5 * (1 - Pos.y);

ps shader
이곳에서 하는 일은 단순하게 이전 패스에서 넘겨준 텍스쳐를 위치를 조금씩 바꿔서 여러번 얻어와서
뭉개주는 것 밖에 없다.

float4 sum = tex2D(RT, texCoord);
   for (int i = 0; i < 12; i++)
   {
      sum += tex2D(RT, texCoord + sampleDist0 * samples[i]);
   }
   return sum / 13;

pass 2 blur
- 위 패스의 blur와 완전히 같다.

pass 3 combine

드디어 내가 원했던 결과화면이 나왔다.
DOF 영역은 깔끔하고 그 외 부분은 블러가 먹는 화면....
난 안경을 빼면 눈이 무척 나빠서 늘 DOF 외곽지역....ㅡㅡ;;;;..

vs shader
할게없다. 그냥 ps에게 위 blur의 vs 처럼 uv 좌표만 넘겨줄뿐...

ps shader
원본이미지로 blur한 rendertarget texture와 원본이미지를 적당히 섞어줘야 한다.
sampler Blur1;
sampler RT;

float4 sharp = tex2D(RT, TexCoord);
float4 blur = tex2D(Blur1, TexCoord);

두 이미지를 섞어주는 데 첫 패스에서 alpha에 저장한 깊이값을 사용한다.
return lerp(sharp, blur, saturate(range* abs(focus-sharp.a)));  


blur패스를 한번만 한 결과는 아래와 같다.

뭉개진 부드러움정도를 자세히 보면 확실히 차이가 난다.
하지만.. 알겠지만 blur 자체가 꽤나 많은 부하를 먹는다는걸 잊지말자.

부분 요소별로 살짝 살펴보자.

이 값은 원본 이미지에서 구한 깊이값만을 찍은 것이다.
return float4(sharp.a, sharp.a, sharp.a, 1.0);

이 값은 깊이값에 focus값을 적용한 결과값이다.
return float4(abs(focus-sharp.a), abs(focus-sharp.a), abs(focus-sharp.a), 1.0);
focus는 어차피 상수값이고 sharp.a는 거리값이다.
이 두 값은 0~1사이의 값이므로 focus를 적당히 중간값으로 설정해 주면 된다.

이 값은 range까지 적용한 값이다.
float resultVal = saturate(range* abs(focus-sharp.a)); 
return float4(resultVal, resultVal, resultVal, 1.0);
range값을 적당히 줘서 값을 부풀렸다.

range, focus, rendertarget.depth의 값을 적용하여 lerp의 rate를 지정한다.

DOF.rfx


여기까지가 DOF의 기본 개념에 대한 설명이다.
그런데!!! DOF도 계속해서 발전해서 같은개념의 다른 방식을 사용하여 퀄리티를 끌어올렸다.
그래서 지금까지 설명한 것을 Simple Depth Of Fiel라고 하자.


GDC 2004에서 소개된 Advance DOF가 있다.

Scheuermann_DepthOfField.pdf


컴퓨터 그래픽스 에서는 핀홀(바늘 구멍 카메라) 카메라 모델을 사용한다는걸 우선적으로 알아줘야 한다.


핀홀카메라를 사용하면 깊은 심도 때문에 또렷한 이미지를 얻을 수 있다.
하지만 실제 카메라는 렌즈를 사용하고, 그렇기 때문에 한정된 수치를 가진다.
(바로 이것이 Depth Of Field의 발생원인.)

핀홀 카메라에 대한 링크
http://dica.dcinside.com/study_listN.php?id=3030&code1=20&code2=10&s_mode=&s_que=&page=3&



References

wiki - Depth Of Field
http://ko.wikipedia.org/wiki/%ED%94%BC%EC%82%AC%EA%B3%84_%EC%8B%AC%EB%8F%84

심도란 무었인가?
http://blog.daum.net/usstory/5264427

심도와 조리개의 관계, 착란원
http://blog.naver.com/PostView.nhn?blogId=isue79&logNo=80171033118

심도와 착란원
http://blog.naver.com/hohwang1/10033991880






'Study > M's Lecture' 카테고리의 다른 글

Depth Of Field 2 (Advanced DOF)  (0) 2013.04.13
행렬  (0) 2013.03.21
Shader 개발을 위한 툴  (0) 2013.03.12
5. 왜 물은 물처럼 보이는 걸까?  (0) 2013.02.20
4. 왜 물은 물처럼 보이는 걸까?  (2) 2013.01.28
TAGS.

Comments