OpenGL

[OpenGL-11] object Viewer 구현하기 (3)

zamezzz 2017. 5. 27. 17:33

 Object Viewer 구현하기 (3)



안녕하세요.


오늘은 obj viewer 구현하기 세번째 포스팅을 진행하겠습니다.


이번 포스팅이 이 프로그램의 마지막 포스팅이 될 것 같네요 !


지난 포스팅까지는 obj파일로 표현된 객체를 구현하고, 이를 화면 중앙에 적절한 크기로


위치시키는 것 까지 진행하였습니다. 그리고 카메라와 콜백함수까지 구현하였죠.


오늘은 재질과 조명 효과를 구현하고 프로그램을 마무리해보겠습니다.


그럼 시작해보겠습니다.


● 재질 및 조명


이번 포스팅의 첫 번째는 재질입니다. 그리도 두 번째는 조명이죠


사실 재질과 조명은 하나로 설명하고 구현하는 것이 더욱 좋은데요.


자세한 세부 설명 및 개념은 아래 'Lighting' 포스팅을 참고하시면 되겠습니다.

http://zamezzz.tistory.com/154


결국 위의 재질과 조명의 각 ambient, diffuse, specular 값을 이용하여 원하는


Phong Model을 구현하는 것이 우리의 목표입니다.

Phong Model을 구하는 식 기억하시나요? 다음과 같았습니다.

적정의 ambient, diffuse, specular 값을 구하기 위해서는 여러번 테스트를 직접


해보시는 것이 중요합니다. 저는 예를 들어 아래와 같이 정했습니다.


vec4 lAmb = vec4(0.1,0.3,0.2,1); //빛의 ambient 값

vec4 lDif = vec4(0.3,0.5,0.3,1); //빛의 diffuse 값

vec4 lSpc = vec4(1,1,1,1); //빛의 specular 값


vec4 mAmb = vec4(0.1,0.4,0.1,1); //재질의 ambient 값

vec4 mDif = vec4(0.8,0.8,0.8,1); //재질의 diffuse 값

vec4 mSpc = vec4(spec,spec,spec,1); //재질의 specular 값

float mShininess = 50.0; //하이라이트 집중도


Shininess에 대한 설명을 잠깐하자면 ..


위의 그림에서 보이는 PHONG SHADING의 흰색 매끈한 부분이 Shininess의 정도입니다.


그 값이 클수록 집중받는 흰 하이라이트 부분이 넓어지죠. 이 또한 적당한 값으로


설정을 해주어야 사실적인 객체가 완성됩니다.


자 그럼 이제 계산을 해줍시다.


각 요소를 계산하여 Shader에서 넘겨주어 최종 계산을 진행하겠습니다.


ambient끼리, diffuse끼리, specular끼리 곱해주면 되겠죠 ?


vec4 amb = lAmb * mAbm;

vec4 dif = lDif * mDif;

vec4 spc = lSpc * mSpc;


이제 이 값들을 shader로 넘겨주어 계속 계산을 진행합니다.


main code -> Vertex Shader -> Fragment Shader로 넘어가며 그 계산이 완료됩니다.


Vertex Shader로 값을 넘겨주기 위해서는 'glGetUniformLocation(shader,'param')'


를 이용하여 Uniform변수로 넘겨줍니다. 예를 들어 ... 아래와 같습니다.


GLuint myShader;

myShader = InitShader("vertexShader.glsl", "fragmentShader.glsl");

glUseProgram(myShader);


GLuint uAmb = glGetUniformLocation(myShader, "uAmb");

glUniform4f(uAmb, amb[0], amb[1], amb[2], amb[3]);


glutSwapBuffers();


이런식으로 되겠죠.



사용할 Shader 파일을 초기화 하고, 해당 파일로 현재 코드에서 정한 값을 넘겨줘요.


이제 쉐이더에서 최종적으로 수식계산을 해주면 되는데요. 위의 식에 하나씩 값을


대입해서 정리해보겠습니다. (다시 Phong model 계산식을 리마인드...)

- ambient는 uAmb로 넘겨주었습니다.

- diffuse는 uDif로 넘겨주었습니다.

- specular는 uSpc로 넘겨주었습니다.

- n (shininess) 또한 uShine으로 넘겨주었습니다.


이제 우리가 계산해야 할 것은 N, L, R, V 벡터 4가지입니다. 이것만 계산하면 끝이죠


이를 위해 아까 몇 가지 Matrix를 더 넘겨주어야 하는데요. 간단하니 명칭만 보겠습니다


vec4 uModelMat : transformation이 적용된 객체입니다.

vec3 uNormal : normal벡터입니다.

vec4 uLightPos : 광원의 위치입니다.


자 이제 위의 4가지 벡터를 구해봅시다.


N은 노말벡터였죠, 현재 객체에 노말벡터를 곱해주면 구할 수 있습니다.

vec4 N = uModelMat * vec4(uNormal, 0);

uNormal은 vec3이므로, vec4로 변환합니다. 

translate영향을 받으면 안되므로 0으로 설정하였습니다.


P는 현재 객체의 위치입니다.

vec4 P = uModelMat;


L은 빛 방향 벡터입니다. 빛의 위치에서 현재 위치를 빼주면 방향이 나오겠죠

vec4 L = uLightPos - P;


V는 우리가 보는 방향 (즉, 카메라의 방향입니다) 원점에서 객체를 보는 방향이죠

vec4 V = vec4(0,0,0,1) - P;


R은 반사각입니다. 이는 L과 V를 이용하여 구할 수 있습니다.

vec4 R = V+L;


자 이제 모두 구했으니.. 이를 최종적으로 계산해주면 됩니다.


계산식은 아래와 같으니 한 번 보시죠.


float NL = max(dot(N, L), 0);

float VR = pow(max(dot(R, N), 0), uShine);


fPhong = uAmb + uDif*NL + uSpc*VR;


굉장히 복잡하게 느껴지는 Phong model 구현하기입니다.


하지만 이렇게 직접 한 번 해보신다면 익숙해질 수 있습니다.


그럼 지금까지의 노력의 결과물을 볼까요. 이를 보면 기분이 좋아진답니다...


bunny.obj파일을 비교해보겠습니다.


한눈에 봐도 어느쪽이 Phong model이고 Flat model인지 아시겠죠 ?


이렇게 자연스럽게 객체가 그려진답니다.




이렇게 object viewer 포스팅을 마치겠습니다.


하나하나 살펴보고 구현할게 많아서 어려움이 있었지만, 생각보다 결과물이 이쁘게 


등장하여 다행입니다. 중간에 잘못된 부분있으면 알려주시면 감사하겠습니다!!


그럼 이만 포스팅을 마칠게요. 긴 글 읽어주셔서 감사합니다. 


모두 object viewer구현 성공을 바라겠습니다.

반응형

'OpenGL' 카테고리의 다른 글

[OpenGL-10] object viewer 구현하기 (2)  (0) 2017.05.17
[OpenGL-9] object viewer 구현하기 (1)  (13) 2017.04.06
[OpenGL-8] Lighting  (0) 2017.03.16
[OpenGL-7] Projection Matix  (0) 2016.12.31
[OpenGL-6] Model View Matrix  (2) 2016.11.13