본문 바로가기
컴터/OpenGL

[OpenGL] Phong shading, Blinn-Phong shading

by 나 진짜 못차마 2023. 6. 10.
728x90

경북대 '컴퓨터그래픽스' 강의 백낙훈 교수님의 강의를 듣고 복습하기 위한 게시글입니다.

게시글의 내용은 강의 또는 구글링을 통해 공부하였습니다.

이미지 자료는 출처를 밝히거나 직접 그려 사용하였습니다

이전 글에서 Phong reflection model을 구현할 수 있는 방법으로는 크게 3가지가 있다했다.

이번에는 그 중 마지막인 Phong shading을 다룬다.

추가로 Phong shading에서 살짝 더 발전한

Blinn-Phong shading도 살짝 다룬다.


Phong shading

Phong shading 이 나온 배경은

이전 Gouraud shading은 vertex 단위로 phong equation을 계산하고 값을

polygon 내부에서 bi-linear interpolation한다.

근데,

이 Gouraud shading을 적용하다 보니 잘 되지 않는 경우를 발견하게 된다.

 

예상값

gouraud shading 실제 결과 값

그 경우는 주로 길거나, 큰 polygon에서 발생한다.

polygon에 수직인 방향으로 빛을 쏜다고 가정해보자.

예상대로라면 polygon의 가운데 부분은 정반사가 일어나 highlight가 일어나야한다.

 

근데 gouraud shading은 polygon의 가운데 부분에서는 전혀 계산을 하지않는다.

끝부분인 vertex에서의 phong equation값을 사용한다.

더군다나,

만약 polygon의 끝부분 vertex에서 normal vector가 light source와 이루는 각도가 좀 벌어져서

highlight나 reflection이 거의 없는 상황이 생길 수 있다.

결과적으로 polygon의 양 끝부분에서는 상대적으로 어두운 값만 계산되어서 나오는 상황이라면,

해당 vertex의 색상을 가지고 bi-linear interpolation을 하니까

polygon 전체가 어두운 색상이 된다.

그래서 Phong shading은 Gouraud shading의 단점을 해결하기위해

phong equation을 vertex단위가 아닌,

fragment 단위로 처리한다.

illustration by 백낙훈 교수님

phong equation을 구하기 위해서는 주어진 점에서의 normal vector가 필요하다.

그러기위해 각 vertex의 normal vector를 입력 받아서 normal vector를 interpolation하자는 아이디어를 낸다.

이 방식의 장점은

위의 gouraud shading의 단점과 같이 polygon 중간에서의 reflection을 놓치는 것을 막을 수 있다.

진행 순서는

  1. vertex shader에서 각 vertex의 normal vector를 계산한다.
  2. rasterizer에서 normal vector를 bi-linear interpolation 한다.
  3. fragment shader에서 각 fragment normal vector를 사용해서 Phong equation을 계산한다.

gouraud shading의 vertex단위 처리에 의해 약간의 거친 부분, 빛이 번지는 부분이 있지만,

phong shading은 한층 부드럽게 빛 처리를 하는 걸 볼 수 있다.

계산량은 많지만 지금의 graphics의 많은 경우에 phong shading을 사용한다.


Blinn-Phong Shading

Phong reflection model에서 사용하는 phon equation 중에서

가장 계산이 많은 부분이 specular reflection, 특히 (R · V)를 계산하는 부분이란 걸 찾아냈다.

왜 복잡하냐면,

R vector가 3차원 공간 상에서 N과 L을 가지고 R을 계산하는게 논문 발표한 1977년 당시에는 어려운 계산이였다.

( 이전 phong reflection model 에서 specular reflection 부분에서 R vector를 구하는 과정부터 이후 과정까지 복잡하긴 했다.)

그래서 이걸 빠르게 할 수 있는 방법을 찾다보니

halfway vector를 제안한다.

halfway vector는 L 과 V의 가운데에 있는 벡터인 평균이 된다.

계산을 하다보니 수학적으로 증명된 것이

라는 식이 나오게 되는데,

이 각도 Φ 가 H와 N이 이루는 각 Ψ의 2배가 된다는 것을 밝혀낸다.

이 성질로 부터

라는 식이 된다.

하지만 실제로 N · H 는 cosΨ 만 나온다.

그래서 cosΦ를 정확히 계산하지말고, 근사치를 사용하자는 것이다.

cos 함수를 볼 때, 각도가 90 일 때 0, 0일 때 1이 나온다.

cosΦ 의 어떤 값이 나올 때,

각 Φ의 절반인 Ψ를 이용한 cosΨ의 값은 cos 함수의 특성상 cosΦ 보다 큰 값이 나올 것이다.

그래서 N · H 는 R · V보다 항상 값이 커질 수 밖에 없다.

실제 근사값을 적용시킬 때는

기존의 specular reflection 구하는 식에서

R · V에서 α 승(제곱) 했던 것에 반해서,

N · H 에서 α'(알파 프라임)으로, shininess 값을 훨씬 높혀준다.

그래서 α' 는 최소한 2α 이상으로 선택해야된다.

실험적으로 보면 실제로는 3~4배 이상으로 가야 비슷해진다.

왼쪽 그림은 α = α'로 적용했을 때,

reflection 부분이 번져있는 걸 볼 수 있다.

그래서 α' > 3 or 4α 를 적용하면 번지는 부분이 줄어들면서 거의 phong shading과 비슷해진다.

기존의 Phong shading에서 R vector를 계산할 때 많은 계산이 필요했는데 그걸 안해도되니,

속도가 훨씬 빨라졌다.

현재는 이런 이점 때문에 blinn-phong shading을 많이 사용한다.

728x90

'컴터 > OpenGL' 카테고리의 다른 글

[OpenGL] Flat Shading, Gouraud Shading  (0) 2023.06.10
[OpenGL] Phong Reflection Model  (0) 2023.06.10
[OpenGL] Shading  (0) 2023.06.10
[OpenGL] View Frustum, FOV(field of view)  (2) 2023.06.10
[OpenGL] Look-At, Orthographic Projection  (2) 2023.06.10