728x90



짐벌락이란?

= x축(Pitch) y축(Yaw) z축(Roll) 의 세축이 회전을 하다가

 특정 축이 특정각으로 회전을 했을 때 두 축이 겹쳐서 한축이 소실되는 현상을 말한다.

 


짐벌락 현상이 일어나는 이유!

      1. 오일러 각을 이용하기 때문에

      2. 오일러 각 회전을 순차적으로 하기 때문에

 


짐벌락 현상을 완벽하게 막을 방법?

 - 단정적으로 말하자면 존재하지 않다.

즉, 우리는 짐벌락현상을 최대한 피하는 방법 밖에 없다.

 


짐벌락 현상을 최대한 피하는 방법

     1. 오일러 각 회전의 순서를 바꾼다.

     2. Axis라는 임의의 축회전을 이용한다.

     3. 쿼터니언을 이용한다.

 


오일러 각 회전의 순서 바꾸기

- 잘 생각해보면 xyz 축회전에서 순서를 바꾸어 나타낼 수 있는 가지수는 총 6가지이다.

 

즉, xyz xzy yxz yzx zxy zyx 로 회전의 순서를 바꿀 수 있다.

 


여기서 잠깐! 순서를 정하는 방법을 알아보자.

     1. 가장 자주 회전하게 될 축을 먼저 회전한다.

     2. 가장 회전을 안하게 될 축을 2번째로 회전한다.

     3. 남은 축을 회전한다.

 

이유!? 순서에 의한 짐벌락 현상은 두번쨰 회전하는 축이 90도(-90도)를 회전하게 되면

 1번째 축과 3번째 축이 겹치면서 발생한다.

즉, 순서를 바꿔서 최대한 피하는 방법은 두번째 회전하는 축이 90도가 되지 않으면 된다.

다시 말해 두번째 회전하는 축이 회전을 자주하지 않으면 90도가 될 확률이 낮기에 위와같은 순서로 회전한다.

 

 

Axis라는 임의의 축회전을 이용하는 방법

- 사실 아직 정보가 부족하다. 우선적으로 알고 있는 정보는

'D3DXMatrixRotationAxis' 라는 함수 이다.

이 함수는 인자로 결과행렬을 내 뱉고, 임의의 축이 될 벡터와 회전을 먹일 회전행렬을 인자로 원한다.

 

여기까지가 필자가 알고있는 Axis에 대한 정보이다.

 

하지만 이 임의의 축회전도 문제가 있다.

 

임의의 축을 놓고 회전할 때 보간의 처리( 선형보간, 구면보간 )의 문제로 회전 시에 뚝뚝 끊겨보이게 된다.

 

이 문제를 해결할 쿼터니언이 존재한다.




출처 : http://blog.naver.com/qkfkf123/60170135935

728x90
728x90

z-fighting 이란 두개의 폴리곤(primitive)이 유사한 z-depth값을 갖고있어 노이즈가 발생한것 처럼 깜박거리는 현상이다.(폴리곤이 깨지거나 랜덤하게 겹쳐지게 된다)

이는 z-buffer알고리즘을 사용하는 3D그래픽스 시스템에서는 피할수없는 현상이며 프로그래머가 잘 판단해서 피해가는 것이 해결책이다.




일반적으로 16,24,32 bits크기의 z-buffer를 사용하기 때문에.. 즉, 값이 유한하기 때문에 발생할 수밖에 없다.

 

3차원 공간상에 두개이상의 폴리곤이 동일한 위치에 겹쳐있는 경우와 폴리곤이 서로 근접해있는 경우에 발생한다.

near와 far plane간의 간격을 조절하면 대부분의 경우 이러한 현상을 회피할 수 있다.

카메라에 근접할 수록 z-depth값에 대한 가중치가 높아지기 때문에 주로 near plane 값을 카메라로부터 멀리 조절하면 된다.

 

참고로 z-buffer의 계산식은 아래와 같다

2^(Depth Bit) * ( (zFar / ( zFar - zNear ) ) + (Far * zNear / ( zNear - zFar )) / distance )

 

====================================================

[참고사이트]

http://en.wikipedia.org/wiki/Z-fighting

http://jmonkeyengine.com/mark/?p=136

http://en.wikipedia.org/wiki/W-buffering#W-buffer

[출처] z-fighting 관련|작성자 http://blog.naver.com/softcool/110025105010상공작


출처 : http://blog.naver.com/softcool/110025105010

728x90
728x90

Axis - Pitch (Head) : X, Yaw : Y, Roll : Z



728x90
728x90

FOV는 카메라의 시야각을 의미한다. 

기본적으로 FOV 수치가 높으면 시야각은 넓어지고 사물은 멀리 있는 것 처럼 보인다.

반대로 FOV 수치가 낮으면 시야각은 좁아지고 사물은 가까이 있는 것 처럼 보인다.

 

다음의 두 스크린 샷을 통해 확인해보자.


 

                              FOV : 100                                                              FOV : 80

 

같은 위치의 카메라 시야각에 따라 다양하게 보인다.

또한 FOV의 수치가 커질수록 왜곡의 정도도 심해진다. (카메라의 광각렌즈)

 

이런 다양함을 가지고 각 장르의 게임마다 FOV를 다르게 가져간다.

 

가령 1인칭 게임의 대표인 FPS 장르는 FOV를 40이하로 하는 것이 보통이다.

정면을 주시하며 정확한 타겟팅이 필요한 게임에서 왜곡이 심하고 좌우 시야가 넓은 높은 시야각은 불필요하다. (스나이퍼가 줌을 당기는 것은 그 순간 FOV 수치를 매우 낮게 변경한 것이다.)

 

TPS 장르의 경우에는 FOV가 40 ~ 70 정도이다.

TPS는 3인칭 장르로 캐릭ㅌ너의 액션이 추가된다. 때문에 캐릭터의 모든 액션들을 카메라에 담기 위해서는 다소 높은 시야각을 요구한다. 캐릭터가 좌, 우로 빠르게 이동하는 과정에서 FOV가 낮다면 휙휙 지나가게 되어 어지러움을 느끼게 된다.

(기어워는 55기준으로 상황에 따라 바뀌는 것으로 알고 있다.)

 

RPG는 넓은 필드가 있기 때문에 시야각이 넓다.

 

마지막으로 FOV(시야각)에 따른 표현의 차이를 정리해본다.

 

1. 낮은 FOV

 - 카메라에 보이는 좌우폭이 좁다.

 - 상대적으로 사물이 가까워 보인다. (거리감이 작게 느껴진다.)

 - 왜곡이 적다.

 - 정면으로 이동시 속도감이 떨어진다.

 

2. 높은 FOV

 - 카메라에 보이는 좌우폭이 넓다.

 - 상대적으로 사물이 멀어보인다. (거리감이 크게 느껴진다.)

 - 왜곡이 많다. (엔진에 따라 차이가 있지만, 100이상에서 확실히 느껴진다.)

 - 정면으로 이동시 속도감이 많다.



출처 : http://cafe.naver.com/comeonqa.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=79&

728x90
728x90

1. 렌더링 파이프라인


렌더링 파이프라인이란, 3D 그래픽을 어떻게 그려나가는지에 대한 절차의 설명입니다. 





가. 정점 데이터. 


3D 그래픽이 그려지기 시작하면, 우선 정점 (vertex) 부터 일정한 위치에 그려지게 됩니다. 
그 정점에는 순서를 나타내는 번호가 씌여져 있어서, 각 점을 순서대로 연결하여 면을 만들게 됩니다. 



나. 삼각형 분할


각 vertex를 연결해서 삼각형을 그리게 됩니다. 이 때 시계방향으로 그리냐 시계 반대방향으로 그리냐에 따라 앞 뒷면이 정해지게 되고, 혹은 양 면을 다 그릴 수도 있습니다. 이것은 렌더링 기본설정에서 정해지게 됩니다.  



   



다. 정점 쉐이더 (vertex shader) 

정점 쉐이더에서는 기본적으로 행렬연산에 의한 변환작업이 주로 이루어집니다. 

변환작업이란 다음과 같은 개념이지요. 엄밀하게 말하면 아래 그림과는 조금 다른 개념이지만, 따로 설명하기가 어렵군요.






기본적으로 오브젝트는 자기 자신이 가지고 있는 각각의 좌표계로 되어 있습니다. 






일단 그걸 월드 좌표계로 변환해줍니다. (행렬을 곱해서 만듭니다.) 





다시 그걸 카메라좌표계로 전환을 합니다. 
그걸 카메라에서 바라보면 이런 느낌이 됩니다. 
이것을 Orthographic 또는 Isometric 이라 부릅니다. 
(원근감이 없는 2D 게임 같은 이미지가 됩니다.)








이것에 다시 투영행열을 계산하여 원근감을 구현해 줍니다. 

즉 원근감이 없는 2D 게임같은 이미지는 한 번 더 계산이 줄기 때문에 조금더 빠른 방식이라는 것을 알 수 있습니다. 



이상의 4가지 단계가 일반적인 vertex shading의 기본 단계입니다. 

이후 이 단계에서 Normal 값과 Light Direction, View Direction 등을 이용하여 빛을 계산 할 수도 있습니다. 



2. Clipping


오브젝트 중 화면에 보이지 않는 부분을 잘라서 안 그려버리는 방법입니다. 

당연하게도 보이지 않는 것은 그리지 않는 것이 유리합니다. 



3. Backface Culling

카메라에서 보이지 않는 방향의 면은 그리지 않습니다. 반대방향은 어차피 그려도 보이지 않으니까요. 



이 이외에도 사실 여러 종류의 culling 등이 존재하고 있습니다 .



4. Rasterizing 

이것은 본격적으로 모니터라고 하는 2차원의 어느 부분'픽셀'에 찍힐 것인지를 결정하는 것입니다. 
3차원 이미지는 필연적으로 2차원의 평면인 '모니터' 에 찍혀져야 하기 때문에 다시 2차원의 점으로 환산하는 작업이 필요하게 됩니다. 이것을 Rasterzation 이라고 합니다. 


http://commons.wikimedia.org/wik...n_bw.svg

5.  PixelShader

이 단계에서 픽셀쉐이더가 시작됩니다. 
이 부분에서 하는 일은 Resterizing이 결정되어 찍힐 픽셀이 결정된 상태에서 쉐이딩 - 빛 계산 - 을 시작하게 되는 것으로, 보다 정밀한 계산이 가능해 집니다. 
또한 이 부분에서 텍스쳐 셈플러를 통해 텍스쳐가 입혀지게 됩니다. 

6.  Alpha Test / Alpha blending 
알파 테스트와 알파 블렌딩은 무척 중요한 개념입니다. 
여기에서 sorting의 개념이 같이 들어가기 때문이지요. 
이전에도 설명했듯이, 텍스쳐에는 알파 채널이 들어갈 수 있습니다. 
그 알파 채널은 보통 256 단계로 부드럽게 들어갈 수 있습니다만, 그런 경우 문제가 생길 수 있습니다. 
예를 들어 반투명의 유리창이 있고 그 뒤에 공이 있다면, 공은 유리창 뒤에 있음에도 불구하고 '유리창에 반쯤 영향받은 채 보여야'
할 것입니다. 즉 '뒤에 있는데도 보여져야 한다' 라는 명제가 생기게 되는 것이므로, '뒤에 있으면 그리지 않는다' 라는 기본 깊이테스트를 무시해야 하는 것이지요. 

그렇지만 알파 테스트를 적용하게 하면, 256단계의 부드러운 알파 채널의 단계 중 일정 부분을 정해서 그 투명도를 0 또는 1로 정의해 버립니다. 즉 '반투명' 이란 것은 없고, 이 픽셀이 보이는가 안보이는가만 임의대로 (예를 들어 100보다 크다던가) 결정해 버리는 것입니다. 이렇게 하면 일반 오브젝트 그리는 것과 별 차이 없이 처리할 수 있는 장점이 있지만 알파 채널의 퀄리티는 다소 떨어지게 됩니다. 하지만 대부분의 게임에서는 이 알파 테스트를 사용하게 됩니다 .(다시 말해서, 이전시간에 설명했던 것과 같이 DDS 데이터를 아무리 RGBA 4:4:4:8 로 한다 하더라도 결국 4:4:4:1과 같이 출력되게 되는 것이므로 쓸 데없이 알파 채널을 8비트로 그릴 필요가 없다는 것입니다) 

알파 블렌딩은 이보다 더 복잡하게 됩니다. 위에 설명했던 것 처럼 알파 블렌딩이 들어가게 되면, '모든 픽셀은 언제나 보일 수 있다' 라는 정의가 작동하게 됩니다. 반투명의 유리가 수 십장 겹쳐져 있어도 전부 보이는 것처럼 말입니다. 
그렇게 되면 더 이상Z 버퍼에 의한 거리 판별은 무의미하게 되며, 모든 픽셀은 이 픽셀이 보인다는 가정하에 얼마나 보이는가를 계산해야 되는 상황이 됩니다. 불투명한 오브젝트라 하더라도 일단 계산에는 무조건 올라가게 됩니다. 그러면서도 깊이 테스트는 필요해 질 수 밖에 없는 것이, 중간에 불투명한 오브젝트가 끼어 있을지도 모르기 때문입니다. 불투명한 오브젝트라면 그 뒤의 것들은 그려지지 말아야 하니까요. 이렇게 복잡한 계산 때문에, 제대로 sorting 하지 않으면 아래 그림처럼 나타나게 됩니다. 

그러므로 알파 블렌딩이 사용되게 되면, 나머지 것들을 다 그리고 난 후 알파 블렌딩이 되는 것들만 모아서 위치값을 재 정렬하고, 다시 그것들을 찍으면서 모든 픽셀의 색상을 계산해 줘야 합니다. (얼마나 반투명 되는지 말이지요) 
당연하게도 이것은 엄청난 시간을 들이게 되는 작업이므로, 현재의 게임에서는 되도록 피해야 하는 방법입니다. 



이것은 주로 머리카락 등에서 그래픽 디자이너의 요청으로 사용되어지도록 요청될 수 있습니다. 부드러운 머리카락을 Alpha test 따위로 거칠게 만들어 버리고 싶은 그래픽 디자이너는 없으니까요. 그렇지만 그렇게 되면 역시 오른쪽과 같은 sorting 문제가 발생하면서 다시 그래픽 디자이너의 원망을 듣게 될 것입니다. 
때문에 기술적으로 이해가 높은 그래픽 디자이너가 있는 프로젝트에서는, 머리카락에 알파 블렌딩을 거의 사용하지 않고 처리해 버리기도 합니다. 직접 몇 덩어리씩 모델링 해버리거나, 알파 테스트를 사용하되 해상도를 높여서 지저분한 흔적을 최대한 줄여버리는 꼼수를 사용할 수도 있는 것입니다. 

그렇지만 알파 블렌딩을 아예 사용하지 않을 수는 없습니다. 대표적인 것은 이펙트입니다. 이펙트는 사실상 90% 이상이 알파 블렌딩만으로 처리되며, 높은 수준의 이펙트가 부하를 유발하는 주범이 되는 것은 이 때문입니다. 
또한 반투명한 유리나 비치는 옷 같은 경우도 알파 블렌딩을 사용할 수 밖에 없는 부분입니다. 

그러므로 효율적인 알파 블렌딩을 사용하기 위해서는 '아예 과감히' 사용하는 것이 가장 좋습니다. 
예를 들어 원피스의 옷 한벌에 텍스쳐를 한 장 사용하고,  가슴팍 부분 일부만 반투명으로 하느니 차라리 원피스 전체를 반투명으로 하는 것이 나을 것입니다. (아니면 반투명을 전혀 안쓰도록 디자인하던가 말입니다) 

이것은 Anti-aliasing과도 혼동될 수 있습니다만, 이것은 텍스쳐의 alpha 부분의 정밀도를 계산하는 방법이므로 antialiasing과는 근본적으로 차이가 있음을 주의하시기 바랍니다.

7.Z test 
어느 오브젝트가 앞에 있는지를 판별하는 것입니다. 기본적으로 Z 버퍼(깊이 버퍼)를 이용하여 멀고 가까운 거리를 판별합니다. 
하지만 정밀도가 무한하지 않기 때문에 너무 근접한 오브젝트의 경우에는 오류가 있을 수도 있습니다.

8. 스텐실 테스트 
반사 되는 장면을 그릴 때 거울 부분에만 그려지는 것 처럼 일부분에만 그려지도록 마스킹하는 테스트입니다. 

9. Fog
일정 깊이값을 대상으로 안개의 색상을 더합니다. 
편법으로, 절대 갈 수 없는 원경을 저급한 퀄리티의 폴리곤으로 멀리 만들어 놓고, fog 색의 2*2 의 텍스쳐를 입혀 놓는 편법을 사용하여 게임의 최적화를 하기도 합니다. 




출처 : http://egloos.zum.com/chulin28ho/v/5241665

728x90
728x90

피사계심도란?

W

Depth OField 라고도 하며 


렌즈로 일정 거리에 피사체의 초점을 맞추면 앞면과 뒷면의 일정한 거리 내에 초점이 맞는데

이때 그 범위를 이르는 말로

게임 내에서는 씬 내에 있는 가장 멀리 있는 오브젝트와 가장 가까이 있는 오브젝트 사이의 거리 

즉,카메라에 초점이 맞는 거리 범위를 말한다



크라이시스2 Bokeh 합성 DOF 영상



DOF OFF


DOF ON


DOF OFF


DOF ON


피사체가 초점에 앞에 있으면 렌즈에서 모아진 초점이 렌더타겟에서 보여지는 위치보다
안쪽이 되어 버리므로 감광되는 영역이 넓어지며




피사체가 안쪽에 있으면 렌더타겟에서 보여지는 위치보다 앞쪽에 초점이 위치하게 되므로
한번 모인 빛이 다시 퍼져서 렌더 타겟에 그려진다 ( 마찬가지로 감광되는 영역이 넓어짐)


.
초점이 맞춰져있는 부분은 선명한 화면을.. 나머지 초점이 맞지않는 부분은 블러를 적용하여 흐리게 한다



먼저 일반 화면을 렌더링하고 화면으로부터의 거리를 깊이값으로 렌더링한다.
다음, 렌더링 화면으로부터 뭉갠화면을 생성하고
마지막으로 렌더링한 깊이 값의 정보로부터 초점이 맞는 부분은 선명한 화면
초점이 맞지 않는 위치에는 뭉개진 화면을 합성한다



마지막에 최종 화면을 합성할때 에는 선형보간으로 이루어진다

 return lerp(OriginalImage, BlurredImage, saturate(Range *abs(Focus - PixelCameraZ)));


DOF구현의 기본은 카메라 공간 내에 있는 뭉개진화면인 Far 평면과 Near 평면과의 비교를 할수 있도록
카메라 공간에 그려질 픽셀의깊이값을 변환하는 것이다.

아래는 NDC 공간을 카메라 공간의 좌표로 변환하는데 사용하는 왼손좌표계용 프로젝션 매트릭스이다




아래의 방정식은 위에 투영행렬에 세번째 열에 있는 4D 동차 벡터를 곱한결과를 보여주고 있다




24.2는 매트릭스 w = z일경우 w에 의해 동차적으로 나누어진 최종 깊이 버퍼 방정식이며, 
이를 Z에 대해 풀면 카메라 공간으로 깊이 버퍼 값을 다시 역 변환하는데 사용할수 있다(24.3)

또한, 카메라 공간상의 픽셀의 거리는 깊이 버퍼를 가져오는 대신
씬이 렌더링 되는 동안 카메라 공간상의 각 픽셀에 깊이 값을
렌더 타겟의 알파 채널에 저장할 수 있다

 VS_OUTPUT VS(VS_INPUT Input)

{
    .....

    // 색성분에 깊이값을 넣음

    // 조명계산 필요시, 깊이값을  색성분의 w값에만 사용하고 다른성분에 조명을 계산한값을 출력 
    Out.Color = pos.z / pos.w;

    .....

    return Out;
}

float4 PS(VS_OUTPUT Input) : COLOR0
{
    float4 Out;
    .....

    // 알파 성분에 깊이값 저장
    Out.a = Input.Color.w;

    .....

    return Out;
}


다음  축소 버퍼를 사용해 뭉갠 화면을 준비한 후 초점이 될 깊이값을 어플리케이션에서 세팅한다


이후 강도를 조절하고 lerp()함수를 사용해 선명한 화면과 뭉개진 화면을 합성한다.


 // 카메라 공간으로 역변환

float PixelCameraZ = (-NearClip * Q) / (Depth - Q);


사용자정의 Focus 값과 Range 값은 원래 이미지와 뭉갠이미지 사이를 선형 보간하기 위하여 구한

픽셀의 카메라 거리와 함께 사용되며 최종 화면으로 합성된다


 // 선형 보간

return lerp(OriginalImage, BlurredImage, saturate(Range * abs(Focus - PixelCameraZ)));


이때 절대값을 취하는 이유는 피사계심도가 초점이 맞는 위치를 기준으로 앞쪽과 뒤쪽 모두에서

흐리게 뭉개져야 하므로 초점이 맞는 위치를 기준으로 어느족으로 깊이값이 증가하더라도

뭉개지는 양이 증가 할수 있도록 한것이다

(절대값이 아닌 제곱 값을 취해도 되나 출력상태가 약간 틀리므로 보고 나서 선택 하도록)


이 밖에 Bokeh 합성이 있으며 자세한건 위키피디아를 참조..



NDC11 "올바른 HDR을 이용한 Bloom과 DOF"  이창희님




                 1. 원본이미지                   2. Bokeh 합성                  3. 가우시안 블러 적용 DOF

위키피디아 링크 : http://en.wikipedia.org/wiki/Bokeh

이외에 스타크래프트 2는 CoC Map (Circle of Confusion)을 사용한다고 했다


스타2의 DOF


그림에서 보면 블러를 먹일 양을 결정하진 텍스처 인것 같다

.. 최대치의 블러를 먹일 부분과 초점이 맞는

부분의 사이의 Fade 효과가 들어가는 것일지도... 

대충 봤을때는 현재 픽셀의 블러를 먹일 것인가에 대한 데이터를 가진 텍스쳐인거 같다




출처 : http://blog.naver.com/sorkelf/40149186261


728x90
728x90


728x90

+ Recent posts