스키닝 속도 질문입니다!!

2D, 3D, 다각형, 픽셀 등 게임의 그래픽 프로그래밍에 관한 포럼입니다.

Moderator: 류광

Locked
궁금이
Posts: 237
Joined: 2005-01-19 11:06
Location: ProjectS

Post by 궁금이 »

mesya wrote:컥 20만폴리곤 50프레임이라..
쉐이더로 하셨나요? 혹시 더 안좋은 그래픽카드에서 테스트해본 데이터는 없을까요?
저사양에서 효과적인 스키닝속도를 얻으려고 하는중이거든요.
fx5700 이라면 비교가 어려울 것 같습니다.

20만 폴리곤 전부에 애니메이션 하셨는지도 궁금하구요,
position 과 normal 전부 스키닝 처리 해주셨는지도 궁금합니다~
보간도 하셨는지 궁금합니당 알려주세요~~

(혼자서 도배하는군요)
2004년 겨울쯤에 개발하던 게임이 상용화를 하고 시간이 좀 생겨서.. 미친듯이 스키닝이 매달렸었습니다.
그 이후.. 지금은 엔진을 사서 개발하다보니 한동안 잊고 지냈던 쓰레드이군요 :D

집에가서 자세히 확인을 해야겠지만..

기존에 CPU로 하던걸 쉐이더로 변경해서 구현했고요..
지포스4-TI에서 테스트도 했었는데.. 기억이 정말 가물가물한데.. 30프레임 정도였나?? ㅠ_ㅠ

800 폴리곤 250개인데.. 800 폴리곤이 캐릭터였으니 전부 애니메이션하였고,
position, normal 전부 스키닝했습니다. 보간도 물론 했는데..
글을 적으면서 생각이 났네요...
보간의 경우는 캐쉬이용해서 한거라서..
250개 캐릭터모두를 매 프레임마다 보간 계산했다고 하기는 좀 그렇네요 :oops:

적고보니.. 별로 구현 잘한것 같지는 않네요.. 다른 분들이 비웃을까 두렵다는 ㅠ_ㅠ


p.s 그 당시에 테스트할때 캐릭터 하나가 폴리곤 800개짜리다보니.. 별로 만족을 못했었습니다.
250개 중에서 멀리있는건 텍스쳐에 렌더링해서 빌보드로 그리는식으로 꼼수를 부려서..
프레임 팍팍 올라가게 하고서는.. 혼자 즐거워한 기억이 ㅋㅋ

p.s 2003년, 2004년에 비회원으로 스키닝 질문 엄청 많이했었습니다 -_-
그 당시 메비님의 리플 많이 참조했고요.. (이 기회를 드려서 감사를 ㅎㅎ)
<리버스>라는 게임때문에 나왔던 글 쓰레드가 있는데.. 그 쓰레드도 많이 참조했었습니다.
mmoboy
Posts: 144
Joined: 2006-02-02 11:15

음.. 저같은 경우에는

Post by mmoboy »

CPU로..
폴리곤 3174개짜리 오브젝트를 100개 찍어서 17프레임이 나오는군요 -_-;
캐릭터 많아지면 장사 없네요..
물론 실제 인게임에서는 메쉬 LOD, 애니메이션 LOD, 프레임LOD 등등 다 때려박겠지만..
LOD없는 메쉬로만 찍을경우에는 꽤 힘들군요..ㅎㅎㅎ

CPU: P4-2.4
VGA: X800 Pro 입니다만.. 100개가 넘어가니까 VGA자체는 큰 영향을 주지 않는것 같습니다.

어셈으로 SSE를 사용했고.. CPU Pipline, Data Trans 최적화를 했습니다.

그리고.. 스키닝은
Position, Normal, TangentU, TangentV 4개를 했고요..
Position과 Normal만 했을시에는 22~3프레임정도 나옵니다..
뭐 해먹고 사나.. ('' ) ( '')
mesya
Posts: 268
Joined: 2005-02-28 20:08

Post by mesya »

와우, 엄청난 속도인거 같은데요~
cpu pipeline, data trans 최적화를 하셨다구 하셨는데..
노하우좀 알려주세요~~
이지노리, 김현중
mmoboy
Posts: 144
Joined: 2006-02-02 11:15

음 노하우랄꺼 까지는 없고요..

Post by mmoboy »

스키닝 쪽을 설계하실때 연산쪽에만 보통 신경쓰시는데..
데이터 전송쪽에 신경을 많이 써주셔야 할듯 합니다..

VertexBuffer의 Lock을 거는 것도 그렇고.. vector3나 matrix 한줄이라도..
최대한 전송없이.. burst모드 믿고 =연산자로 복사 했다간..
효율이 많이 떨어집니다.

일반 C/C++로 코딩하신다면 연산 루프 안에 분기문은 절대로! 넣어선 안되고요
예를들어..

for( size_t cVertex = 0; cVertex < m_lstVertex.size(); ++cVertex )
{
.................
if( m_lstVertex[ cVertex ] )...... <- 절대로 불가..
............
......
}

연산루프는 분기문, 데이터 복사 없이 한번에 고속으로 끝날수 있도록 유지
시켜주는것이 중요합니다..

그리고 어셈으로 짜신다면..
SSE를 활용하는것이 좋겠죠..
보통 D3DX....관련 유틸리티도 내부적으로 SSE를 많이 쓴다고 하지만..
D3DX의 경우 내부에서.. 분기문이 좀 사용되어져 있습니다.
사실 그래서 효율이 떨어지죠..
뭐 요즘 CPU가 좋아서 분기 예측을 한다고 하지만.. 고속으로 돌아가야하는
스키닝 루프에서 분기문이 쓰일경우에는 .. 예측이 빗나가고..
캐시 미스까지.. 날 확률이 매우매우 높기 때문에 안쓰는것이 좋습니다.

SSE같은 SIMD를 사용한다고 해서 float연산이 확연하게 빨라지는 것은 아니기 때문에..
잘짜여진 일반 C/C++ 수학함수가 D3DX유틸 함수를 쓴것보다 더 빠를때가 많습니다.

그래서 좋은 방법은..
Lock을 건 Pointer를 직접 연산함수에 넣어서 내부에서 FULL 어셈으로 한번에
돌려 버리는 것입니다..

vector3 *pDestPos = (vector3*) m_pVB->Lock( xxxxxxxxxx );

// 여기서 내부에서 인라인으로 모두 계산해서 직접 pDestPos에 넣어줌
ComputeSkinning( pDestPos, pSrcPos, pSkinData, pAnimMatrix, nTotalVertex );

m_pVB->Unlock();


이런식으로요.. 아 쓰고 나니까 몬말인지 모르겠네 ㅡ..ㅡ

아무튼 펜티엄CPU는 내부적으로 동시에 처리할수 있는 파이프라인이 몇개 있습니다..
전 3개로 알고 있습니다 ( --; 맞나..)
아무튼 3개의 다른 명령어를 1클럭에 처리하는 구조죠..
그래서 어셈 명령어 배치도 신경써서 배치해야 합니다.. 실제로 배치를 바꾸니.. VTune으로..
프로파일링 해보면.. 차이가 좀 나더군요..

그리고 어셈 내부에서 memory <----> cpu register 의 .. 이동은 역시..최소화 시키는것이
좋습니다.. 역시 데이터 이동이니.. 한 줄 차이라도 캐릭터 한마리 띄웠을떄 100프레임 이상
차이가 날때가 있습니다.
(뭐 어셈 조금이라도 하시는 분들은 다 알고 있을겁니다. 저도 어셈허접이라 -,.- )

아무튼 이런식으로 이러저러해서 3500 ~ 4000폴리곤 넘는 캐릭터 한마리만 띄우고
Position벡터, Normal벡터, TangentU 벡터, TangentV벡터 4종류를 스키닝하고..
메모리를 아끼기 위해서.. 인덱스와 버텍스를 단한개만 정적으로 쓰는지라..
텍스쳐 좌표와 인덱스 좌표는 memcpy로 떄려버리고..

디퓨즈 맵, 노말맵...에 라이트 1개...... 그리고 애니메이션..본은 100개 정도?...
프레임단위로 계속 보간해서..
650~700프레임정도 나옵니다..

근데 이게 빠른거 같진 않을거 같네요..

제가 어셈을 잘 짜는편도 아니고요.. 또 요즘에는 CPU의 SIMD유닛보다는..
GPU의 ALU가 훨씬 flops도 높고.. 또 쉐이더에서 연산하면 Lock을 걸필요도
없이.. 비디오 메모리상에서 바로 이뤄지니까.. 데이터 이동도 없을테니..

GPU가 좋을수록 GPU로 스키닝하는게 좋을듯 합니다
저희 게임은 본이 많아서.. GPU스키닝은 포기해서리 ==;


마지막으로 제가 생각한 캐릭터 엔진의 전체 파이프라인은..

일단 SSE는 기본으로 사용하고요..
본이나 폴리곤 갯수에 따라서.. CPU와 GPU가 ...
나눠서 스키닝 하는 방식을 생각하고 있는데..
캐릭터 엔진 자체가.. 병렬처리가 가능하도록.. 멀티 쓰레드로 작성된다면
꽤나 높은 성능을 보여줄거 같더군요....................

아 술좀 마시고 들어와서 이상 잡설이었습니다 @,@
뭐 해먹고 사나.. ('' ) ( '')
babosungil
Posts: 37
Joined: 2005-11-13 15:21

윽 대단하시다는

Post by babosungil »

2.4에 mx440에서 겨우 1300개짜리 50개 + 외각선 ( 2패스라고 하나요? ) 해서 겨우겨우 30프레임넘겨서 좋아라 하고 있었는데 좌절 먹었다는... ㅠ.ㅠ 다시 위에분 말씀하신 충고대로 좀더 깔끔하게 만들어보면 낳아지려나요~ ^^;
그곳에 가자! PG + BS!!
mesya
Posts: 268
Joined: 2005-02-28 20:08

Post by mesya »

pos, normal
SSE 스키닝, 구면쿼터니언보간까지 해서
cpu 3.0, 그래픽카드 x700 에서 20만폴리곤 23~24프레임정도 나오네요..
x1300 에선 20만폴리곤 33프레임,
x1300 에서 30만폴리곤 25프레임 정도 되네요.
휴.. 더 올려야겠군요 ㅠ,.ㅠ
이지노리, 김현중
Locked