시퀀스를 통해 스폰한 스켈레탈메시 액터가 스폰 직후 Facial 표현을 위한 모프 타겟을 갖고 있는데, 이것이 적용되지 않아 확인 중에 있습니다.
r.SkinCache.Mode 를 0으로 설정하면 이 문제가 해결되어, 관련 코드를 살펴보던 중 의심 가는 내용이 있어 문의드립니다.
재현에 필요한 프로젝트를 구성하기위해서는 모프 타겟이 포함된 애셋등을 포함하여야 하는데, 이것이 여의치 않아 코드흐름으로만 문의드리는 점 양해부탁드립니다.
먼저 저희 프로젝트는 나나이트를 사용하지 않아, SkeletalRenderGPUSkin에서 발생하는 문제입니다.
이해하기로는 다음의 순서로 GPU 스키닝을 수행하는 것 같습니다.
ProcessStage_MeshDeformer-> ProcessStage_SkinCache -> ProcessStage_Inline-> ProcessStage_Upload
이번 프레임 모프 사용 여부의 결정은 SkinCache 스테이지의 SetupSection() 함수 내부에서 MorphVertexBuffer->SectionIds.Contains(SectionIndex) 를 통해 수행하는 것 같습니다.
그런데 MorphVertexBuffer->SectionIds는 Upload Stage의 MeshObject->UpdateBufferData() -> UpdateMorphVertexBuffer() 시점에 가서야 채워지는 것 같습니다.
이 때문에 첫 프레임에서 모프를 갱신하지 못하는 것으로 파악하고있습니다.
그래서 다음과 같은 방식으로 MorphVertexBuffer의 최초 업데이트가 호출되기 전이면, SectionIDs를 먼저 한번 채워주도록 수정을 시도하였습니다.
결과는 의도한 대로 동작하였는데요.
void FSkeletalMeshObjectGPUSkin::ProcessUpdatedDynamicData(FRHICommandList& RHICmdList, FGPUSkinCache* GPUSkinCache, EGPUSkinCacheEntryMode Mode)
{
// 앞부분 생략
if (Mode == EGPUSkinCacheEntryMode::Raster)
{
// RayTracing-specific LOD's can't have a separate morph target buffer at the moment because there is only one morph vertex buffer across the entire mesh.
if (GEnableMorphTargets && LODData.GetNumVertices() > 0 && (bHasWeightedActiveMorphs || bHasExternalMorphs))
{
bMorphNeedsUpdate |= GForceUpdateMorphTargets != 0;
if (bMorphNeedsUpdate)
{
LOD.MorphVertexBufferPool->SetCurrentRevisionNumber(CurrentRevisionNumber);
}
MorphVertexBuffer = &LOD.MorphVertexBufferPool->GetMorphVertexBufferForWriting();
// Force an update if this is the first use of the buffer
if (!MorphVertexBuffer->bHasBeenUpdated)
{
bMorphNeedsUpdate = true;
#if WITH_CUSTOM
// SkinCache가 SetupSection을 수행할 때(이 함수 뒷부분) bMorph 판단을 위해
// SectionIds가 필요한데, 원래는 다음 단계(Upload)에서 채워집니다.
// 이를 방지하기 위해 여기서 미리 DynamicData의 SectionIds를 복사해둡니다.
MorphVertexBuffer->SectionIds = DynamicData->SectionIdsUseByActiveMorphTargets;
#endif // WITH_CUSTOM
}
if (bMorphNeedsUpdate)
{
LOD.MorphVertexBufferPool->SetUpdatedFrameNumber(BoneTransformFrameNumber);
}
}
else
{
MorphVertexBuffer = nullptr;
bMorphNeedsUpdate = false;
}
}
// 뒷부분 생략
}
이러한 수정이 적절할까요? 아니면 다른방식으로 수정해야할까요?
의견 부탁드립니다. 감사합니다.