UE5 Nanite 渲染流程

UE5 Nanite 渲染流程

UE5 Nanite 支持静态网格Mesh。

启用Nanite

UE5 Nanite 渲染流程_第1张图片
启用和弃用Nanite,对比发现顶点和三角形的个数明显少了很多。
UE5 Nanite 渲染流程_第2张图片
Root:\Program Files\Epic Games\UE_5.0EA\Engine\Source\Developer\AssetTools\Private\AssetTypeActions\AssetTypeActions_StaticMesh.cpp
启用和弃用Nanite功能主要是涉及相关UStaticMesh的重新构建过程。

void FAssetTypeActions_StaticMesh::ExecuteNaniteEnable(TArray<TWeakObjectPtr<UStaticMesh>> Objects)
{
	for (auto StaticMeshPtr : Objects)
	{
		UStaticMesh* Mesh = StaticMeshPtr.Get();
		if (Mesh)
		{
			Mesh->NaniteSettings.bEnabled = true;
			Mesh->Build();
			Mesh->MarkPackageDirty();
			Mesh->OnMeshChanged.Broadcast();
		}
	}
}

void FAssetTypeActions_StaticMesh::ExecuteNaniteDisable(TArray<TWeakObjectPtr<UStaticMesh>> Objects)
{
	for (auto StaticMeshPtr : Objects)
	{
		UStaticMesh* Mesh = StaticMeshPtr.Get();
		if (Mesh)
		{
			Mesh->NaniteSettings.bEnabled = false;
			Mesh->Build();
			Mesh->MarkPackageDirty();
			Mesh->OnMeshChanged.Broadcast();
		}
	}
}

Root:\Program Files\Epic Games\UE_5.0EA\Engine\Source\Runtime\Engine\Private\StaticMeshBuild.cpp

目前Nanite功能仅支持编辑器模式下启用。

void UStaticMesh::Build(bool bInSilent, TArray<FText>* OutErrors)
{
#if WITH_EDITOR
	
#endif // #if WITH_EDITOR

	BatchBuild({ this }, bInSilent, nullptr, OutErrors);
}
void UStaticMesh::BatchBuild(const TArray<UStaticMesh*>& InStaticMeshes, bool bInSilent, TFunction<bool(UStaticMesh*)> InProgressCallback, TArray<FText>* OutErrors)
{
#if WITH_EDITOR
	
#else
	UE_LOG(LogStaticMesh, Fatal, TEXT("UStaticMesh::Build should not be called on non-editor builds."));
#endif
}

渲染过程

与其他UPrimitiveComponent类似,通过创建FPrimitiveSceneProxy类来执行具体渲染。

Root:\Program Files\Epic Games\UE_5.0EA\Engine\Source\Runtime\Engine\Classes\Components\StaticMeshComponent.h

class ENGINE_API UStaticMeshComponent : public UMeshComponent{
    /** For nanite enabled meshes, we'll only show the proxy mesh if this is true */
	UPROPERTY()
	uint8 bDisplayNaniteProxyMesh:1;
}

Root:\Program Files\Epic Games\UE_5.0EA\Engine\Source\Runtime\Engine\Classes\Engine\StaticMesh.h

class UStaticMesh : public UStreamableRenderAsset, public IInterface_CollisionDataProvider, public IInterface_AssetUserData, public IInterface_AsyncCompilation
{
    /** Settings related to building Nanite data. */
	UPROPERTY()
	FMeshNaniteSettings NaniteSettings;
 /**
	 * Returns true if thee mesh has valid Nanite render data.
	 */
	ENGINE_API bool HasValidNaniteData() const;
}

Root:\Program Files\Epic Games\UE_5.0EA\Engine\Source\Runtime\Engine\Private\StaticMesh.cpp

bool UStaticMesh::HasValidNaniteData() const
{
	if (const FStaticMeshRenderData* SMRenderData = GetRenderData())
	{
		return SMRenderData->NaniteResources.PageStreamingStates.Num() > 0;
	}

	return false;
}

Root:\Program Files\Epic Games\UE_5.0EA\Engine\Source\Runtime\Engine\Public\StaticMeshResources.h

/**
 * FStaticMeshRenderData - All data needed to render a static mesh.
 */
class FStaticMeshRenderData
{
    Nanite::FResources NaniteResources;
}

Root:\Program Files\Epic Games\UE_5.0EA\Engine\Source\Runtime\Engine\Private\StaticMesh.cpp

void FStaticMeshRenderData::InitResources(ERHIFeatureLevel::Type InFeatureLevel, UStaticMesh* Owner)
{
    NaniteResources.InitResources();
}

void FStaticMeshRenderData::ReleaseResources()
{	

	NaniteResources.ReleaseResources();
}
FPrimitiveSceneProxy* UStaticMeshComponent::CreateSceneProxy()
{
	

	// Is Nanite supported, and is there built Nanite data for this static mesh?
	if (UseNanite(GetScene()->GetShaderPlatform()) && GetStaticMesh()->HasValidNaniteData() 
	#if WITH_EDITORONLY_DATA
		&& !bDisplayNaniteProxyMesh
	#endif
	)
	{
		LLM_SCOPE(ELLMTag::StaticMesh);

		// Nanite is fully supported
		return ::new Nanite::FSceneProxy(this);
	}



	FPrimitiveSceneProxy* Proxy = ::new FStaticMeshSceneProxy(this, false);
#if STATICMESH_ENABLE_DEBUG_RENDERING
	SendRenderDebugPhysics(Proxy);
#endif

	return Proxy;
}

Root:\Program Files\Epic Games\UE_5.0EA\Engine\Source\Runtime\Engine\Private\InstancedStaticMesh.cpp

class ENGINE_API UInstancedStaticMeshComponent : public UStaticMeshComponent
FPrimitiveSceneProxy* UInstancedStaticMeshComponent::CreateSceneProxy()
{
	

		// Is Nanite supported, and is there built Nanite data for this static mesh?
		if (UseNanite(GetScene()->GetShaderPlatform()) && GetStaticMesh()->HasValidNaniteData())
		{
			return ::new Nanite::FSceneProxy(this);
		}
		// If we didn't get a proxy, but Nanite was enabled on the asset when it was built, evaluate proxy creation
		else if (GetStaticMesh()->HasValidNaniteData() && NaniteProxyRenderMode != 0)
		{
			// Do not render Nanite proxy
			return nullptr;
		}
		else
		{
			return ::new FInstancedStaticMeshSceneProxy(this, GetWorld()->FeatureLevel);
		}

}

Root:\Program Files\Epic Games\UE_5.0EA\Engine\Source\Runtime\Engine\Private\HierarchicalInstancedStaticMesh.cpp

class ENGINE_API UHierarchicalInstancedStaticMeshComponent : public UInstancedStaticMeshComponent:public UStaticMeshComponent

FPrimitiveSceneProxy* UHierarchicalInstancedStaticMeshComponent::CreateSceneProxy(){
    
// Is Nanite supported, and is there built Nanite data for this static mesh?
		if (UseNanite(GetScene()->GetShaderPlatform()) && GetStaticMesh()->HasValidNaniteData())
		{
			return ::new Nanite::FSceneProxy(this);
		}
		// If we didn't get a proxy, but Nanite was enabled on the asset when it was built, evaluate proxy creation
		else if (GetStaticMesh()->HasValidNaniteData() && NaniteProxyRenderMode != 0)
		{
			// Do not render Nanite proxy
			return nullptr;
		}
		else
		{
			return ::new FHierarchicalStaticMeshSceneProxy(this, GetWorld()->FeatureLevel);
		}
  }

其他

其他涉及Nanite渲染的相关类。

Root:\Program Files\Epic Games\UE_5.0EA\Engine\Source\Runtime\Engine\Public\Rendering\NaniteResources.h
Root:\Program Files\Epic Games\UE_5.0EA\Engine\Source\Runtime\Engine\Public\NaniteSceneProxy.h
Root:\Program Files\Epic Games\UE_5.0EA\Engine\Source\Runtime\Engine\Public\Rendering\NaniteStreamingManager.h
Root::\Program Files\Epic Games\UE_5.0EA\Engine\Source\Developer\NaniteBuilder\Public\NaniteBuilder.h

你可能感兴趣的:(UE4,Nanite,UE5)