1일1알

DirectX11 학습 - StaticMesh 본문

DirectX11

DirectX11 학습 - StaticMesh

영춘권의달인 2024. 3. 31. 17:17

단순한 도형이 아닌 가상 공간에 배치되는 물체들은 정점들이 굉장히 많을 것이다.

이런 물체의 정점 정보들을 코드로 하나하나 채워줄 수 없기 때문에 외부에서 만든 파일을 읽어서 사용해야 한다.

fbx 포맷의 파일을 사용했고, Assimp라는 라이브러리를 사용해 fbx파일을 읽어서 파일을 분석한 뒤 필요한 정보만 뽑아서 따로 저장하고 사용할 때는 따로 저장한 정보를 읽어서 사용했다.

필요한 정보만 따로 저장하는 이유는 Assimp라이브러리를 사용해 파일을 로드하면 이런저런 잡다한 정보들까지 모두 추출하여 시간이 오래 걸리기 때문이다.

 

shared_ptr<Converter> converter = make_shared<Converter>();
converter->ReadAssetFile(L"Tank/Tank.fbx");
converter->ExportMaterialData(L"Tank/Tank");
converter->ExportModelData(L"Tank/Tank");

// 오브젝트가 계층 구조로 구성되어있을때는 자신의 부모 오브젝트의 좌표계를 기준으로 한다.
// 따라서 오브젝트를 대표하는 좌표계인 Root 좌표계로 변환하는 행렬을 구해 저장한다.
bone->transform = bone->transform * matParent;

 

fbx파일의 경로를 통해 파일을 로드하고 Material, Model 정보를 추출하여 지정한 경로에 저장한다.

이때 오브젝트가 계층구조로 되어있을 경우에는 자신의 부모의 좌표계를 기준으로 하는 좌표로 저장되어있다.

따라서 오브젝트를 대표하는 좌표계인 Root 좌표계로 변환하는 행렬을 구해 저장한다.

 

 

만약 계층구조를 고려하지 않고 물체를 화면에 띄운다면 의도하지 않은 좌표로 쉐이더에 전달이 되기 때문에 위의 사진처럼 부품들이 중앙에 모인 상태로 띄워지게 된다.

 

/////////////////////////////////
// *********** cpp **************
/////////////////////////////////

const uint32 boneCount = _model->GetBoneCount();
for (uint32 i = 0; i < boneCount; i++)
{
	shared_ptr<ModelBone> bone = _model->GetBoneByIndex(i);
	boneDesc.transforms[i] = bone->transform;
}
_shader->PushBoneData(boneDesc);

_shader->GetScalar("BoneIndex")->SetInt(mesh->boneIndex);

//////////////////////////////////
// ************ shader ***********
//////////////////////////////////

cbuffer BoneBuffer
{
	matrix BoneTransforms[MAX_MODEL_TRANSFORMS];
};

uint BoneIndex;

MeshOutput VS(VS_IN input)
{
	MeshOutput output;
	output.position = mul(input.position, BoneTransforms[BoneIndex]);
	output.position = mul(output.position, input.world);
	output.worldPosition = output.position.wyz;
	output.position = mul(output.position, VP);

	output.uv = input.uv;
	output.normal = mul(input.normal, BoneTransforms[BoneIndex]);
	output.normal = mul(output.normal, (float3x3)input.world);

	output.tangent = mul(input.tangent, BoneTransforms[BoneIndex]);
	output.tangent = mul(output.tangent, (float3x3)input.world);

	return output;
}

 

계층구조를 적용하기 위해 Root 변환 행렬들을 쉐이더의 ConstantBuffer에 넘겨주고, 해당 행렬의 인덱스로 함께 넘겨준다.

버텍스 쉐이더에서 Root변환을 통해 오브젝트를 대표하는 Root좌표계로 모두 변환해준 뒤 World 변환을 적용해준다.

 

 

Root변환행렬을 적용한 뒤 World변환행렬을 적용한 모습니다.

정리하자면 하나의 오브젝트에 서브 오브젝트들이 계층 구조로 구성되어있다면, 서브 오브젝트를 Root 좌표계로 변환하는 행렬을 구해서 이 행렬을 버텍스 쉐이더에서 적용해야 올바른 오브젝트의 모습을 띄워줄 수 있다.

'DirectX11' 카테고리의 다른 글

DirectX11 학습 - 애니메이션  (0) 2024.03.31
DirectX11 학습 - Normal Mapping  (0) 2024.03.30
DirectX11 학습 - Light  (0) 2024.03.30
DirectX11 학습 - Normal Vector  (0) 2024.03.28
DirectX11 학습 - 텍스쳐 입히기, 카메라  (0) 2024.03.28