프로그래밍 공부
작성일
2023. 11. 21. 21:03
작성자
WDmil
728x90

저번에 만들었던 선형보간의 개량이다.

 

선형보간 시, Buffer에 데이터를 넘긴 후, 처리하는 방법이 있고,

 

데이터를 Device에서 처리 후 Buffer에 넘기는 방법이 있는데,

 

전에 만들었던 방법은, 데이터를 넘기기 전 Device에서 처리 후, Buffer에 넘기는것 이었는데,

 

이번에 한 방법은 Buffer에 데이터를 다 때려박은 후 DeviceContext에서 데이터를 처리하는 방법이다.

 

Buffer를 수정한다.

 

	// Frame 구조체: 애니메이션 재생에 사용되는 프레임 정보를 저장하는 구조체
	struct Frame
	{
		int clip = 0;   // 현재 재생 중인 클립의 인덱스
		int curFrame = 0;   // 현재 프레임 인덱스
		float time = 0.0f;  // 현재 프레임에서의 경과 시간
		float scale = 1.0f;  // 애니메이션 재생 속도 조절용 스케일
	};

	struct Motion
	{
		float takeTime = 0.2f;
		float tweenTime = 0.0f;
		float runningTime = 0.0f;
		float padding;

		Frame cur, next;

		Motion()
		{
			next.clip = -1.0f;
		}
	};

	// FrameBuffer 클래스: 상속된 ConstBuffer를 사용하여 프레임 데이터를 GPU에 전달하는 클래스
	class FrameBuffer : public ConstBuffer
	{
	public:
		FrameBuffer() : ConstBuffer(&motion, sizeof(Motion)) {}; // 프레임 데이터를 상속된 ConstBuffer에 전달

		Motion* GetData() { return &motion; } // 프레임 데이터에 대한 포인터 반환

	private:
		Motion motion; // 프레임 데이터를 저장하는 구조체 인스턴스
	};

 

Buffer값을 수정해서, 한개의 구조채를 새롭게 만들고, 전 프레임과 이후 프레임으로 나누어, 버퍼를 전달하게 한다.

struct Frame
{
	int clip;
	int curFrame;
	float time;
	float scale; // 애니메이션 재생 속도 조절용 스케일
};

struct Motion
{
	float takeTime; // 보간시간
	float tweenTime; // 계산 시간
	float running_time;
	float padding;
	
	Frame cur, next;
};

 

위와같이 버퍼구조체를 다시 만든다.

 

// 'SkinWorld' 함수 정의: float4 형식의 'indices'와 'weights' 매개변수를 받음
matrix SkinWorld(float4 indices, float4 weights)
{
    // 결과 변환 행렬을 0으로 초기화
	matrix transform = 0;
	matrix nextTransform = 0;
    // 현재와 다음 애니메이션 프레임을 위한 행렬 선언
	matrix cur, next;
    
    // 시간 보간을 적용한 현재와 다음 애니메이션 프레임을 위한 행렬 선언
	matrix curAnim, nextAnim;
    
    // 현재와 다음 애니메이션 프레임의 구성 요소를 위한 float4 벡터 선언
	float4 c0, c1, c2, c3;
	float4 n0, n1, n2, n3;
    
    // 각 본에 대해 반복 (최적화를 위한 언롤 루프)
    [unroll(4)]
	for (int i = 0; i < 4; i++)
	{
        // 모션 데이터에서 현재 클립 및 프레임 정보를 가져옴
		int clip = motion.cur.clip;
		int curFrame = motion.cur.curFrame;
        
        // 텍스처에서 현재 애니메이션 프레임의 변환 행렬 구성 요소를 로드
		c0 = transformMap.Load(int4(indices[i] * 4 + 0, curFrame, clip, 0));
		c1 = transformMap.Load(int4(indices[i] * 4 + 1, curFrame, clip, 0));
		c2 = transformMap.Load(int4(indices[i] * 4 + 2, curFrame, clip, 0));
		c3 = transformMap.Load(int4(indices[i] * 4 + 3, curFrame, clip, 0));
        
        // 현재 애니메이션 프레임의 행렬 생성
		cur = matrix(c0, c1, c2, c3);
        
        // 다음 프레임의 변환 행렬 구성 요소 로드
		n0 = transformMap.Load(int4(indices[i] * 4 + 0, curFrame + 1, clip, 0));
		n1 = transformMap.Load(int4(indices[i] * 4 + 1, curFrame + 1, clip, 0));
		n2 = transformMap.Load(int4(indices[i] * 4 + 2, curFrame + 1, clip, 0));
		n3 = transformMap.Load(int4(indices[i] * 4 + 3, curFrame + 1, clip, 0));
        
        // 다음 프레임의 행렬 생성
		next = matrix(n0, n1, n2, n3);
        
        // 현재와 다음 프레임을 시간에 따라 보간하여 현재 애니메이션 행렬 생성
		curAnim = lerp(cur, next, motion.cur.time);
		transform += mul(weights[i], curAnim);
	}

	if (motion.next.clip <= -1)
		return transform;
        
	// 모션의 다음 클립 및 프레임 정보를 가져옴
	[unroll(4)]
	for (int i = 0; i < 4; i++)
	{
		int clip = motion.next.clip;
		int curFrame = motion.next.curFrame;
	
        // 클립이 유효한 경우에만 실행되는 조건문
        // 다시 다음 클립의 현재 및 다음 프레임의 변환 행렬 구성 요소 로드
		c0 = transformMap.Load(int4(indices[i] * 4 + 0, curFrame, clip, 0));
		c1 = transformMap.Load(int4(indices[i] * 4 + 1, curFrame, clip, 0));
		c2 = transformMap.Load(int4(indices[i] * 4 + 2, curFrame, clip, 0));
		c3 = transformMap.Load(int4(indices[i] * 4 + 3, curFrame, clip, 0));
        
        // 다시 현재 및 다음 프레임의 행렬 생성
		cur = matrix(c0, c1, c2, c3);
        
		n0 = transformMap.Load(int4(indices[i] * 4 + 0, curFrame + 1, clip, 0));
		n1 = transformMap.Load(int4(indices[i] * 4 + 1, curFrame + 1, clip, 0));
		n2 = transformMap.Load(int4(indices[i] * 4 + 2, curFrame + 1, clip, 0));
		n3 = transformMap.Load(int4(indices[i] * 4 + 3, curFrame + 1, clip, 0));
        // 다음 프레임의 행렬 생성
		next = matrix(n0, n1, n2, n3);
           
        // 현재와 다음 애니메이션 행렬을 tweenTime에 따라 보간하여 최종 애니메이션 행렬 생성
		nextAnim = lerp(cur, next, motion.next.time);
        // 가중치를 곱하여 결과 행렬에 더함
		nextTransform += mul(weights[i], nextAnim);
	}
    
    // 최종 결과 행렬 반환
	return lerp(transform, nextTransform, motion.tweenTime);
}

그리고. 행렬데이터를 재정립하면 끝.

728x90