[Graphics] Shadow

박민주·2022년 6월 19일
0

Computer Graphics

목록 보기
8/8
post-thumbnail

Local Illumination에서 가장 큰 문제는 그림자를 만들 수 없는 것이었음
Direct Illumination을 통해 직접 빛을 받는 부분은 가능했지만,
광원과 내가 그리려는 표면 사이에 물체가 있는지를 찾는 것도 어렵고, 물체의 영향을 계산하는 것도 어려움

Shadow

그림자를 만들기 위해 필요한 것
1. Light source
2. Shador creator와 receivers

  • creator에 의해서 receiver에 creator 영역 만큼의 그림자가 생김
  • creator와 receiver는 각각 다른 물체일 수도 같은 물체일 수도 있음

Light Source Types
- Point source: 그림자의 경계가 깔끔함. 거리가 멀수록 그림자가 커짐
- Area source: 가장 어두운 그림자를 나타내는 umbra가 있고, 빛을 받는 부분이 늘어나는 부분의 penumbra도 있음. 다른 타입의 광원에 비해 그림자가 soft하다는 특징이 있음
- Directional source: point source와 비슷한데 거리와 상관없이 그림자의 크기가 일정함

그림자를 만드는 방법들

  1. 피터팬의 그림자처럼 그림자를 물체와 분리된 하나의 객체로 취급하는 것
  2. 어두운 부분의 영역을 공간으로 표현
  3. 각 점에 대해서 광원에서 그 점이 보이는지 안보이는지 판단

미리 계산된 그림자를 텍스처에 저장해놓는 방법이 있다.
장점은 매우 빠르게 그릴 수 있다는 것이고,
단점은 광원이나 물체가 움직이는 경우 쓰기 어렵다.
또한 벽면이 평면이 아닌 경우 텍스처를 입히는 것이 어렵다.

임의의 물체에 그림자를 렌더하는 두 가지 주요 알고리즘이 있다.

  • Shadow mapping and Shadow volumes
  • real time 에 동작하며, 광원의 관점에서 생각해서 가까우면 black, 멀면 white로 나타낸다.

Shadow map

  • 어떤 한 점에서 광원까지 선을 이은 다음, 그 사이에 교점이 있으면 shadow creator가 있다고 간주
  • 각 픽셀마다 해당 픽셀에서 광원까지의 depth와 해당 광원의 shadow map에 저장된 depth를 비교
    두 거리를 비교해서 해당 픽셀에서 광원까지의 거리가 depth buffer에 적힌 거리보다 길면 shadow 영역임
    (왜냐면 해당 픽셀과 광원 사이에 어떤 물체가 있다는 의미이므로)
    두 거리가 같으면 광원에서 가장 가까운 점이라는 의미이므로 shadow 가 없음
  • shadow map을 활용하면 hard shadow가 굉장히 빨리 계산됨
  • 단점은 depth map의 해상도가 매우 중요해짐. depth buffer에서 봤을 때 그림자를 받는 물체가 광원에서 본 화면의 수직에 가까울 수록 문제

Shadow volumes

  • 광원으로부터 creator의 꼭짓점을 연결한 광선이 세 개일 때, 이 세 개의 광선으로부터 만들어지는 공간 존재
  • 이 공간 안에 포함된 물체는 그림자가 그려지고, 공간 안에 포함되지 않는 물체는 그림자가 반영되지 않음
  • backfacing과 frontfacing을 이용해서 어떤 점이 쉐도우 공간 안에 있는지 없는지 판단
  • 만약 볼륨의 polygon이 두 개의 삼각형이면 merge 해서 표현할 수 있음
    두 삼각형이 겹치는 교선의 변인 경우 두 번 계산할 필요 없이 실루엣 엣지만 뽑아서 외부의 변에 대해서만 계산함

Shadow volume은 Stencil buffer를 통해서도 구현할 수 있음


1. ambient lighting을 가지고 장면 렌더링
- 그릴 때 stencil buffer 에만 기록
2. 카메라가 바라보는 벡터와 면의 수직 벡터가 내적이 양수인 경우 stencil buffer에 그리고 count 증가
3. 2번과 같은데, 면이 back facing인 경우 stencil buffer의 값을 1씩 감소시킴
4. stencil buffer가 0이면 빛을 제대로 받고 있다는 것이므로 diffuse와 specular를 렌더함

Shadow map은 creator와 receiver를 나눌 필요가 없고 Shadow volume는 나누어서 표현

Planar reflection

  • plane은 z=0이라고 가정했을 때, 거울 같은 바닥에서는 단순히 z를 -1로 해서 그림자로 표현할 수 있음
  • Backfacing이 Frontfacing이 됨
  • 이 때 stencil buffer를 쓰는데, 바닥에 그릴 때 shadow receiver인 것에만 그리기 위해서임!
    바닥이 만약 체크무늬이고 그 중 일부만 거울 재질이면, shadow receiver는 거울 재질인 부분만일 것
    (stencil buffer가 0이 아닌 부분에만 그림)

OpenGL에서의 shadow

  • 광원의 입장에서 그린 다음에 z-buffer에 저장해야 함
  • Framebuffer Object를 이용해서 텍스처 이미지 정보 저장
  • OpenGL의 버퍼들은 color buffer, depth buffer, stencil buffer가 있고 하드웨어(디스플레이)에 직접 연결되어 있음
  • Framebuffer object는 메모리에다 적을 수 있는 방식임

Steps

  1. Framebuffer Object를 생성
  2. Texture Object, size and parameter의 집합 생성
  3. Renderbuffer Object를 생성 (실제로 직접 메모리 영역 타겟 중)
  4. Texture2D를 Renderbuffer에 바인딩
  5. Check - 버퍼들이 잘 attach 되었는지 포맷이 잘 되었는지 등 모든 걸 잘 만들었는지 체크
  6. Framebuffer object를 가지고 그림(Draw)

Draw의 details

6-1. bind frame buffer
6-2. viewport 설정
6-3. texture image를 위한 projection, view transform matrix 설정
6-4. 진짜 draw
7-1. bind frame buffer as null
7-2. draw with texture

Shadow map과 Shadow volume 중에
Shadow volume 방법이 더 정확하지만, 계산량은 훨씬 많다.

참고

https://scahp.tistory.com/20

profile
Game Programmer

0개의 댓글