블로그 이미지
˙Jisoo

카테고리

분류 전체보기 (72)
Programming (33)
Game Project (14)
Daily Life (12)
Photo Shots (11)
Total11,447
Today7
Yesterday77

LOD 적용

Programming/DirectX / 2009/07/31 18:52

게임 내에서 이용되는 오브젝트들에 LOD를 적용하는것은 지형 LOD와는 달리 매우 쉬웠습니다.
DirectX 에는 기본적으로 Progressive Mesh 라는것을 지원하여 실시간으로 Mesh의 Face , Vertex 를 조정할 수 있게 해줍니다.
거리에따라 Progressive Mesh 로 지정된 메쉬의 Face 값을 +,- 해주면 간단히 LOD 가 구현이 됩니다.
실제 테스트 결과 오브젝트의 수가 많아질수록 LOD의 적용유무에 따른 속도차이가 엄청났습니다.

LOD를 이용하기위해 Progressive Mesh를 생성하는 과정은 다음과 같습니다.

1. X파일을 일반 Mesh 로 불러옴
2. Mesh 최적화를 해줌
   - CleanMesh , WeldVertices
   (저는 이렇게 두개의 과정만 하였는데 이상이없네요. 상황에따라 다른방식의 최적화가 필요할수도 있습니다)
3. Valid Mesh 를 이용해 DX에서 사용적합한 Mesh 상태인지 확인
4. Progressive Mesh 생성

Progressive Mesh를 사용하려면 Valid Mesh를 반드시 통과하여야 됩니다.
처음 작업을 했을 때 책에 별다른 말이 없어서 1, 4 번 으로 바로 진행하였는데 몇몇 모델 파일들에서 오류가 발생하여 여기저기서 찾아보았더니
Valid Mesh로 부터 OK싸인을 받아야 Progressive Mesh 가 생성된다는 걸 알게되었습니다.
일반적인 게임회사에서는 이미 3D 모델러분들께서 게임에 적합하게 모델링을 해주실 것이라 생각되지만... (그래서 책에 저 작업이 없었던 것 같기도 하고...)
저같이 혼자 공부하는 입장에서는 게임용 모델파일이 아닌 여기저기서 빼오다 보니 Valid Mesh 작업이 꼭 필요한것 같습니다...;;

Posted by ˙Jisoo

댓글을 달아 주세요

기능들을 합쳐갈수록 하나만 있을때 발생하지 않던 문제점도 생기고 신경써줘야 할 부분이 많아지네요.
지형시스템 뒤로는 맵에 배치할 것들을 만들어주려고 하는데 이제 최적화에도 신경을 써야 할 때 같습니다~
지형시스템에서 카메라의 시야에서 보이지 않는부분은 아예 렌더링을 안해서 프레임을 확보 할 예정입니다.
아직 구현방법은 생각해보지 않았는데 좀 빨리 해놓을걸 이제야 하려니 귀차니즘의 발동과함께 작업속도가..............ㅠ.ㅠ
일단 급한건 오브젝트에 애니메이션을 불러오는쪽을 해결봐야겠네요..
지금은 단순히 X파일에서 오브젝트의 버텍스 정보만 얻어오는 수준이라서 아무것도~~없구요
현재 메쉬정보들이 각각 클래스 안에 있어서 몬스터가 많아지면 많아질수록 메모리도 많이 잡아먹는데 몬스터클래스와 오브젝트 정보를 관리할 매니저클래스를 따로 만들어서 메모리를 아껴야 할 필요가 느껴지네요. 3D 메쉬 사이즈가 생각보다 어마어마하더군요..;;

일단 다른 특별한 기능은 없고 지형 클래스에서 getHeight 으로 높이를 구해서 특정 높이 아래 지역에서만 테스트용 모델을 뿌려줬습니다.
그리고 렌더링 하는 부분에서 카메라와의 거리를 측정하여 특정 거리를 넘어가면 렌더링되지 않게 아주 기본적인 처리를 해줬습니다..
이걸 응용해서 카메라와의 거리를 레벨별로 나누고 먼 레벨일수록 모델의 섬세함을 떨어트려서 LOD를 구현 할 예정입니다. (이렇게 하는게 맞는지는 모르겠습니다 ㅡ,.ㅡ;;)



포그를 끄고 확인해보았습니다.
MMORPG 같이 아주 방대한 크기의 게임에서는 필드간의 이동시 로딩도 없애려고 쓰레드를 사용하여 카메라의 범위 내에 들어오기 전에 맵의정보나 로딩이 비교적 긴 파일들을 로딩해온다고 하더군요..
그래서 좀 느린 컴퓨터에서 전혀 안보이던 물체들이 한순간에 생기곤 하나 봅니다.. ^^;





포그를 켰습니다.
포그가 있어도 간혹 모델의 크기가 큰 경우에는 안개속에서 갑자기 뿅 튀어나오는 경우가 있는데
카메라와 거리측정시 모델의 중심과 거리를 재기때문에 거리에서 모델의반경을 빼주니 간단히 해결이 됩니당.


갈길은 먼데 요즘들어 밀려오는 귀차니즘과 FM에 다시 빠져버려서 속도가 너무 더뎌지네요... ㅠ.ㅠ
Posted by ˙Jisoo

댓글을 달아 주세요







이번에는 멀티텍스쳐링과 안개 기능을 넣었습니다.
처음에 멀티텍스쳐링이 안되서 고생을 했는데 알고보니 멀티텍스쳐의 레이어의 개수만큼 지형을 렌더링해줘야되더라구요.
뭐가 잘못되서 그렇게 되는건지 원래 그런건지는 잘 모르겠지만 원래 이런거라면 쓸데없는 연산이 너무 많아져서 나중에 손을 봐야겠네요..
이런 쓸데없는 연산낭비를 해결하기위해 보통 쉐이더로 텍스쳐스플래팅을 구현하는 것 같습니다.
나중에 LOD 구현을 할때도 쉐이더가 필수적이라 LOD 작업 할 때 쉐이더를 적용 할 예정입니다.
LOD가 적용될 때 버텍스가 사라졌다 나타났다 하기때문에 uv좌표가 손실되서 쉐이더가 필수적이라고 하는 것 같습니다.





전에 올렸던 산 맵을 불러온 화면.
현재 텍스쳐들의 상황을 보자면...
모래바닥   --- BaseTexture
풀            --- Blending Texture
풀#           --- Blending Texture Alpha Map
바위         --- Blending Texture
바위#        --- Blending Texture Alpha Map
라이트맵    --- Light Map

이런 구조로 텍스쳐가 로드되어있고

모래바닥 (modulate) 라이트맵
지형 렌더링  // 1pass
풀 * 풀# (modulate) 라이트맵
지형 렌더링 // 2pass
바위 * 바위# (modulate) 라이트맵
지형 렌더링 // 3pass

이런 순서로 렌더링 되고 있습니다.

풀#,바위# 알파맵은 따로 그래픽툴에서 그리는 것이 아닌 자동으로 알파맵이 생성됩니다.
기준은 경사입니다.
평지와 이루는 경사가 가파른부분에 바위를 칠하고 그것보다 조금 덜 가파른곳에 풀을 칠하는 형태입니다.
아래는 풀# , 바위# 알파맵입니다.

   


왼쪽이 풀# 알파맵이고 오른쪽이 바위# 알파맵입니다.
검은부분은 텍스쳐가 적용되지 않고 하얀색으로 갈 수록 텍스쳐의 진하기가 강해집니다.




확인을 해보기 위해 테스트용으로 만들어놓았던 맵파일입니다...
이렇게보니 의도를 파악하기 쉽죠?






덕분에 이런 거칠은 지형도 그냥 지형맵만 만들어주면 알아서 텍스쳐 알파맵을 생성해주니 굉장히 편합니다.
텍스쳐 알파맵 자동생성은 이렇게 두세겹 적용 / 경사기반 까지만으로 해두고 다른 프로그래밍에도 좀 투자를 한 뒤 나중에 여유가 생길때 마다
여러 공식을 만들어서 자동지형생성 알고리즘을 새롭게 만들예정입니다.
풍경보는걸 좋아해서인지 다른것보다 지형에 집착이 강합니다...ㅎㅎ;
Terrain.Render(float age = 30.0f) 이런식으로 하면 지형의 30년 후 변화된 모습이 렌더링되도록 age 기반의 지형시스템을 꼭 만들고 싶습니다 @_@;



아 참... 안개기능에 대해서 안썼는데 정말 써보려고하니 쓸게없네요............;;
그냥 다렉에 기본으로 있는 기능으로 쓴거라...
다음에 쉐이더를 이용한 멋진 안개를 만들면 그때 또 써보도록 하겠습니다...!
Posted by ˙Jisoo

댓글을 달아 주세요


기존에 작업했던 버텍스 노멀 구하기에서 약간의 문제가 있었습니다.
노멀을 구하기 위해 3개의 정점을 이용했는데 한쪽방향으로만 해놨더니 모서리 부분에서 정점 하나가 부족해서리..
그냥 맨 끝쪽만 계산을 안하고있었습니다..



그렇게 놔두다가 보기 흉하고 해서 모서리부분만 정점을 이 전 줄에서 하나씩 빼오고 역벡터로 취해줌으로써 간단하게 예외처리를 해놓았습니다..





빛의 방향을 벡터값으로 정해놓고 여지껏 구했던 버텍스들의 노멀값과 내적을 통해서 음영을 구해줍니다..
DirectX 기본라이브러리에 있는 Directional Light 도 이 방법일 것 같네요...





그림자가 버텍스단위로 너무 딱딱 끊겨서 이상하기에 라이트맵에 블러를 주었습니다.
하지만 음영의 레벨값 차이가 너무 강하죠.. 어두운곳은 너무 어둡고 밝은곳은 너무 밝고....


 


그래서 이와같이 레벨값을 조정해주었습니다.
왼쪽의 결과가 나오기 위해선
기존의값 / 2.0f + 127.0f / 255.0f 의 공식을 사용해주었고
오른쪽의 결과는
기존의값 / 3.0f + 150.0f / 255.0f 의 공식을 사용하였습니다.
( 색상값의 범위 0.0 ~ 1.0 에 1.0 흰색 기준입니다. )

오른쪽 결과에선 너무 밝아서 사라졌었던 부분의 그림자 디테일도 살아났네요..
조금씩 레벨값을 조정하면서 최대한 실사에 근접한 공식값을 찾아봐야겠군요..ㅎㅎ
Posted by ˙Jisoo
TAG D3D, DirectX

댓글을 달아 주세요



외부지형데이터를 raw 파일로 받아서 높이를 지정하도록 하였습니다.
인덱스버퍼 포맷을 변경하여 더 큰 지형을 생성할 수 있도록 하였습니다.
기존에는 16비트 WORD 로 받았는데 256 * 256 크기의 지형에서 크기를 초과하여 끝부분 표현이 제대로 안되었는데
32비트 UINT 로 바꿔줌으로써 훨씬 큰 지형이 표현 가능하게 되었습니다. 이렇게까지 필요한가 싶지만;; 나중에 최적화가 필요하면 조금 낮춰야겠네요.
테스트 해본결과 1024 * 1024 보다도 더 큰 타일 갯수에서도 인덱스를 잘 잡아주고, 지금 계획으로는 1 타일의 단위가 1제곱미터로 작게는 128 * 128 로 시작해서 커봐야 512 * 512 정도의 맵을 사용 할 예정이기에 충분하다고 생각되네요.
Posted by ˙Jisoo

댓글을 달아 주세요



일단 꼭 있어야 할 기능은 이정도면 된 것 같네요.
일단 키보드로 둘러보기가 불편해 마우스로 카메라 회전을 담당하도록 바꿨습니다.
이건 뭐 카메라 클래스 내에선 그대로고 그냥 입력처리루틴 쪽에서만 바꿔주었구요.
아 현재 백페이스컬링을 꺼놔서 양쪽면이 다 보이네요 ㅎㅎ
카메라가 서있는 위치 벡터를 하나 더 만들어서 입력받는대로 벡터를 더해주고 뷰행렬에 넣어주는 방식을 인터넷에서 보아서 그 방식대로 했더니 쉽고 좋네요.
카메라를 더 손보는 것은 플레이어 시스템을 구현 한 뒤로 하고 (그 전까지 특별히 카메라에 다른 기능은 필요 없을 것 같네요)
그 전에 우선 지형생성 클래스랑 오브젝트 매니저 클래스를 만들어 보는 쪽으로 나아갈 예정입니다..
Posted by ˙Jisoo

댓글을 달아 주세요


 비정상적으로 작동할 때의 모습

2차원에서 작업할때완 달리 3차원에서 작업할때는 이리저리 살펴보는것이 필요해서 가장먼저 어느정도 테스트용으로 사용가능한 카메라 클래스를 제작중입니다..
어디까지나 테스트용으로 둘러보기 위한것이므로 아주 기본적인 기능만 있기에 추후 게임용으로 쓰려면 여러군데 손봐야겠지요
테스트 작업용 카메라 만들기도 벅찬데 게임상에서 쓰일 카메라를 제대로 만들수 있을런지 걱정됩니다...;;

오늘 하루동안 yaw pitch roll 과 상하전후좌후 움직이도록 만들어놓으려고 했는데 yaw pitch roll 에서부터 문제가 발생합니다..ㅠ.ㅠ
분명 생각했던 방법대로 짜고 처음 실행해보았을 때는 그런가보다.. 했는데 어째 볼수록 게임에서 카메라를 움직이던 것과 무언가 틀립니다....
(여기서 말하는 게임에서 카메라는 보통 fps게임에서 플레이어가 죽었을 시 spectator 모드로 조종할 때의 카메라 조종 방식)
여기 저기 찾아본 결과 로컬스페이스를 기준으로 yaw 를 움직여서 그랬습니다.
생각해보니 pitch로 카메라가 바라보는 시점이 바뀔경우 로컬스페이스의 업벡터가 같이 변경되고 그 변경된 업벡터를 기준으로 yaw 적용을 하니 원치않던 움직임이 나오는 것은 당연했습니다.






정상적으로 작동하는 모습

그래서 yaw 할때 업벡터를 로컬스페이스의 업벡터가 아닌 월드스페이스 업벡터로 설정하도록 바꾸었습니다.
결과가 더 이상해졌습니다....;;
이때 많이 고민을 했는데 중요한 작업 하나를 빼먹고 있었습니다.
월드스페이스의 업벡터로 yaw를 변경했으면 분명 로컬스페이스 내의 업벡터 값도 변하겠지요. 룩앳벡터 (아.. 도대체 우리말의 표현은 무엇인지;;) 가 바라보는 방향과 같은 선상으로요.
즉 월드스페이스의 업벡터 기준으로 yaw를 적용 한 만큼 로컬스페이스 내의 업벡터도 회전하여야 합니다.
다행히 그렇게 했더니 원하는대로 작동을 하더군요..
그 간단한 한줄짜리 생각을 못해서 참...ㅠ.,ㅠ

pitch 는 그냥 로컬스페이스의 측면벡터,업벡터,룩앳벡터 로 해도 적용 되고 yaw 와 roll에만 이렇게 적용하면 됩니다.
아래는 그냥 나중에 또 까먹고 제 글을 찾아보는 일이 생길까봐.. 간단한 의사코드

1번째 방법 :
yaw( y ) {
  D3DXMatrixRotationAxis ( &matrixRotY , &월드스페이스 업벡터 , y );
  D3DXVecTransformNormal =>  로컬 업벡터 에 &matrixRotY 적용;
  D3DXVecTransformNormal =>  로컬 측면벡터에 ~~~~;
  D3DXVecTransformNormal =>  로컬 룩앳벡터에 ~~~~;
}

2번째 방법:
yaw ( y ) {
  로컬 측면벡터 = 룩앳벡터 와 월드스페이스업벡터 내적;
  로컬 업벡터 = 측면벡터와 룩앳벡터 내적;
  D3DXMatrixRotationAxis ( &matrixRotY , &로컬업벡터 , y );
  로컬 측면,룩앳벡터에 matrixRotY 적용;
}
Posted by ˙Jisoo

댓글을 달아 주세요

Surface Format 에서 사용 가능한 것들
16비트
D3DFMT_R5G6B5
D3DFMT_X1R5G5B5
D3DFMT_A1R5G5B5
D3DFMT_X4R4G4B4
D3DFMT_A4R4G4B4
24비트
D3DFMT_R8G8B8
32비트
D3DFMT_A8R8G8B8
D3DFMT_X8R8G8B8
D3DFMT_A8B8G8R8
D3DFMT_X8B8G8R8
D3DFMT_A2B10G10R10

Adapter Format 에서 사용 가능한 것들
D3DFMT_X1R5G5B5
D3DFMT_R5G6B5
D3DFMT_X8R8G8B8

Frame Buffer Format 에서 사용 가능한 것들
D3DFMT_X1R5G5B5
D3DFMT_R5G6B5
D3DFMT_X8R8G8B8
D3DFMT_A8R8G8B8
D3DFMT_A1R5G5B5
D3DFMT_A2R10G10B10


R이랑 B는 왜 바꿔 쓰는거지...
Posted by ˙Jisoo

댓글을 달아 주세요

최근에 달린 댓글

최근에 받은 트랙백

글 보관함