• 불칸 디버깅
    • 렌더독에서 불칸을 캡쳐하면 패스이름등이 나오지 않음 컬러1 뎊스1 이런식으로 나오고
    • 텍스쳐도 어태치먼트 등으로 표기됨
  • 아래 처럼 컬러패스 뎊스 패스 등을 보기 편한 이름으로 바꾸기
  • 바로 사용할수있는 방법만 알고 싶다면 맨 아래로 가시면 됩니다

 

 

  • 검색해봐도 이렇거나 관련 블로그도 존재함
  • 그래서 달아주기위해 구조를 파악하던중

 

typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectNameEXT)(VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo);

typedef VkResult (VKAPI_PTR *PFN_vkSetDebugUtilsObjectTagEXT)(VkDevice device, const VkDebugUtilsObjectTagInfoEXT* pTagInfo);

typedef void (VKAPI_PTR *PFN_vkQueueBeginDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo);

typedef void (VKAPI_PTR *PFN_vkQueueEndDebugUtilsLabelEXT)(VkQueue queue);

typedef void (VKAPI_PTR *PFN_vkQueueInsertDebugUtilsLabelEXT)(VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo);

..

..

 

#ifndef VK_ONLY_EXPORTED_PROTOTYPES

VKAPI_ATTR void VKAPI_CALL vkQueueBeginDebugUtilsLabelEXT(

    VkQueue                                     queue,

    const VkDebugUtilsLabelEXT*                 pLabelInfo);

#endif

#ifndef VK_ONLY_EXPORTED_PROTOTYPES

VKAPI_ATTR void VKAPI_CALL vkQueueEndDebugUtilsLabelEXT(

    VkQueue                                     queue);

#endif

#ifndef VK_ONLY_EXPORTED_PROTOTYPES

VKAPI_ATTR void VKAPI_CALL vkQueueInsertDebugUtilsLabelEXT(

    VkQueue                                     queue,

    const VkDebugUtilsLabelEXT*                 pLabelInfo);

#endif

  • 이런식으로 디버깅을 위한 함수들히 언리얼 엔진상에 한번 래핑되있는것을 보게됨
  • 또한

 

void FVulkanCommandListContext::RHIPushEvent(const TCHAR* Name, FColor Color)

{

#if VULKAN_ENABLE_DRAW_MARKERS

    if (auto CmdBeginLabel = Device->GetCmdBeginDebugLabel())

    {

        FTCHARToUTF8 Converter(Name);

        VkDebugUtilsLabelEXT Label;

        ZeroVulkanStruct(Label, VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT);

        Label.pLabelName = Converter.Get();

        FLinearColor LColor(Color);

        Label.color[0] = LColor.R;

        Label.color[1] = LColor.G;

        Label.color[2] = LColor.B;

        Label.color[3] = LColor.A;

        CmdBeginLabel(GetCommandBufferManager()->GetActiveCmdBuffer()->GetHandle(), &Label);

    }

#endif

  • 같이 컬러나 이름을 있는 별도의 함수가 존재하는거로 확인이 되어 해당 위치에 값을 넣어봤으나 작동하지 않음
  • 위같은 함수를 포함 다수의 코드에서

 

void FVulkanDevice::VulkanSetObjectName(VkObjectType Type, uint64_t Handle, const TCHAR* Name)

{

#if VULKAN_ENABLE_DRAW_MARKERS

    if(DebugMarkers.SetDebugName)

    {

        FTCHARToUTF8 Converter(Name);

        VkDebugUtilsObjectNameInfoEXT Info;

        ZeroVulkanStruct(Info, VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT);

        Info.objectType = Type;

        Info.objectHandle = Handle;

        Info.pObjectName = Converter.Get();

        DebugMarkers.SetDebugName(Device, &Info);

    }

#endif // VULKAN_ENABLE_DRAW_MARKERS

}

  • 와같이 이미 작성하려는 내용이 존재하는걸 확인 이게 이미 구현이 되어있다고 생각하고
  • VULKAN_ENABLE_DRAW_MARKERS 전처리 매크로를 확인해봄

 

VulkanConfiguration.h

// Enables logging wrappers per Vulkan call

#ifndef VULKAN_ENABLE_DUMP_LAYER

    #define VULKAN_ENABLE_DUMP_LAYER                            0

#endif

#define VULKAN_ENABLE_DRAW_MARKERS                              VULKAN_SHOULD_ENABLE_DRAW_MARKERS

#ifndef VULKAN_ENABLE_IMAGE_TRACKING_LAYER

    #define VULKAN_ENABLE_IMAGE_TRACKING_LAYER                  0

#endif

 

 

VulkanAndroidPlatform.h

#define VK_USE_PLATFORM_ANDROID_KHR                 1

#define VULKAN_ENABLE_DUMP_LAYER                    0

#define VULKAN_DYNAMICALLYLOADED                    1

#define VULKAN_SHOULD_ENABLE_DRAW_MARKERS           (UE_BUILD_DEVELOPMENT || UE_BUILD_DEBUG)

#define VULKAN_USE_IMAGE_ACQUIRE_FENCES             0

#define VULKAN_USE_CREATE_ANDROID_SURFACE           1

#define VULKAN_SHOULD_USE_LLM                       (UE_BUILD_DEBUG || UE_BUILD_DEVELOPMENT) // If enabled Vulkan will report detailed allocation statistics, overrides some tags with custom ones

#define VULKAN_SHOULD_USE_COMMANDWRAPPERS           VULKAN_SHOULD_USE_LLM //LLM on Vulkan needs command wrappers to account for vkallocs

#define VULKAN_ENABLE_LRU_CACHE                     1

  • 매크로를 보면 이미 매크로자체는 활성화 되어있음(디버그와 디벨로 빌드에서 자동 활성화)
  • VULKAN_ENABLE_DRAW_MARKERS 매크로를 검색하다보면 예상대로 원래 일일히 오브젝트 이름등을 입력해야하는 코드 구조가 이미 구성이 되어있음

 

#if VULKAN_ENABLE_DRAW_MARKERS

    inline void SetDebugName(PFN_vkSetDebugUtilsObjectNameEXT SetDebugName, VkDevice Device, VkImage Image, const char* Name)

    {

        VkDebugUtilsObjectNameInfoEXT Info;

        ZeroVulkanStruct(Info, VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT);

        Info.objectType = VK_OBJECT_TYPE_IMAGE;

        Info.objectHandle = (uint64)Image;

        Info.pObjectName = Name;

        SetDebugName(Device, &Info);

}

#endif

  • 이런식으로
  • 그러다 찾게된 함수가

 

void FVulkanDevice::SetupDrawMarkers()

{

#if VULKAN_ENABLE_DRAW_MARKERS

    if (RHI->SupportsDebugUtilsExt())

    {

        // HOTFIX for UE-218250: Disable vulkan draw markers to get around crash/performance issues

        if (FParse::Param(FCommandLine::Get(), TEXT("forcevulkanddrawmarkers")))

        {

            DebugMarkers.CmdBeginDebugLabel = (PFN_vkCmdBeginDebugUtilsLabelEXT)(void*)VulkanRHI::vkGetInstanceProcAddr(RHI->GetInstance(), "vkCmdBeginDebugUtilsLabelEXT");

            DebugMarkers.CmdEndDebugLabel = (PFN_vkCmdEndDebugUtilsLabelEXT)(void*)VulkanRHI::vkGetInstanceProcAddr(RHI->GetInstance(), "vkCmdEndDebugUtilsLabelEXT");

            DebugMarkers.SetDebugName = (PFN_vkSetDebugUtilsObjectNameEXT)(void*)VulkanRHI::vkGetInstanceProcAddr(RHI->GetInstance(), "vkSetDebugUtilsObjectNameEXT");

        }

        if (DebugMarkers.CmdBeginDebugLabel && DebugMarkers.CmdEndDebugLabel && DebugMarkers.SetDebugName)

        {

            bDebugMarkersFound = true;

        }

    }

#if VULKAN_HAS_DEBUGGING_ENABLED

    if (bDebugMarkersFound && GRenderDocFound)

    {

        // running under RenderDoc or other trace tool, so enable capturing mode

        EnableDrawMarkers();

  • 최종적으로 디바이스에서 활성화 되지 않았던 이유가 나와있음(사실은 디버그 레이어등 모든게 활성화는 되어있는데 라벨과 이름만 출력이 안되었던것)
  • 우리가 오브젝트에 이름을 붙이고 패스에 라벨을 붙이는 함수가 여기서 호출이 되어야 하는데
  • 매크로 외에  if (FParse::Param(FCommandLine::Get(), TEXT("forcevulkanddrawmarkers")))
  • 이런조건이 붙어있음 커맨드라인에 forcevulkanddrawmarkers 붙어있어야만 라벨과 오브젝트 이름을 붙여주는 조건이 있었던것
  • 결국 해당 아규먼트를 넣어서 실행하도록 처리하면 렌더독에서 눈에 익은 패스와 오브젝트 이름을 있음
  •  

이미지와 같이 익숙한이름으로 렌더패스를 구분할 있다

 

렌더독에서 아규먼트 붙여서 처리하는건 현재는 안되는듯 바로 아래의 파일 추가로 진행을 해야함

이부분은 엔진버전등에따라 변경될수 있어서 구조기록을 남겨 버전이 달라지더라도 쉽게 파악해서 처리 있도록 준비하는 과정을 남김

 

  • UECommandLine.txt 파일 생성 - 어느곳이든 상관이 없음 디바이스 내에서는 생성하기 어려우니 윈도우에서 생성
  • 내용 붙여넣기 -> -project="../../../[프로젝트이름]/[프로젝트이름].uproject" -forcevulkanddrawmarkers 혹은 -forcevulkanddrawmarkers
  • 해당 파일을
  • 기기\내장 저장공간\UnrealGame\[프로젝트이름] 저장

혹시 안된다면 안드 스튜디오에서 직접 커맨드라인 텍스트를 생성 > 그레이들 빌드(자동)

최종적으로 수정한 내용은 별거 없이 준비되어 있는 기능을 사용한것뿐

가끔 엔진코드보면 정말 이해가 안되게 작성되어 있는 코드들이 존재하는데 이것도 마찬가지

왜 기본적으로 렌더독 활성화시 자동으로 활성화되게 해두지 않았는지 궁금하고 이런부분은 안드로이드 앱 빌드하기나 렌더독 플러그인 설명서에 공지를 해두지 않았는지가 궁금함

 

 

모바일에서 패키징시 액터를 제외하는 기능을 엔진팀에서 추가함

액터의 프로퍼티로 되어있고 Aactor 선언되어있음

 

그런데 실제 뷰에서 사라져야 해당 액터가 사라졌을때의 룩을 있는데 해당 기능이 없어서 구현하게됨

 

사라지는 조건은 프리뷰 피처레벨이 es3.1 이하일때

 

적용되어야 타이밍은 3

 

프리뷰 레벨이 3.1 이하인 상태에서

 

  1. 체크박스를 해제하거나 켤때
  2. 레벨을 로드할때
  3. 프리뷰 레벨을 변경할때

 

체크박스 해제시

  • 프로퍼티 변경시 호출되는 함수에서 수정

 

 

void AActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)

{

    //@pts hidden Actor in Editor U_Es3_1 For ExcludeFormMobile

    if (PropertyChangedEvent.Property &&

        PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(AActor, bShouldBeExcludedFromMobile))

    {

        if (GEditor->GetActiveFeatureLevelPreviewType() >= ERHIFeatureLevel::ES3_1)

        {

            AActor::SetIsTemporarilyHiddenInEditor(bShouldBeExcludedFromMobile);

        }

    }

    //@pts hidden Actor in Editor U_Es3_1 For ExcludeFormMobile

 

 

레벨 로드시

  • 액터가 로드되는 시점에 처리

 

 

void AActor::PostLoad()

{

    Super::PostLoad();

    // add ourselves to our Owner's Children array

    if (Owner != nullptr)

    ..

..

..

        bIsSpatiallyLoaded = GridPlacement_DEPRECATED != EActorGridPlacement::AlwaysLoaded;

    }

    PRAGMA_ENABLE_DEPRECATION_WARNINGS

#endif // WITH_EDITORONLY_DATA

    // Since the actor is being loading, it finished spawning by definition when it was originally spawned, so set to true now

    bHasFinishedSpawning = true;

    //@pts hidden Actor in Editor U_Es3_1 For ExcludeFormMobile

#if WITH_EDITOR

    if (bShouldBeExcludedFromMobile)

    {

        if (UWorld* World = GetWorld())

        {

            ERHIFeatureLevel::Type FeatureLevel = World->GetFeatureLevel();

            if (FeatureLevel <= ERHIFeatureLevel::ES3_1)

            {

                AActor::SetIsTemporarilyHiddenInEditor(true);

            }

        }

    }

#endif

    //@pts hidden Actor in Editor U_Es3_1 For ExcludeFormMobile

}

 

프리뷰 레벨 변경시

프리뷰 레벨 변경시에는 액터에서 처리하기엔 너무 무리가 있어 실시간 프리뷰상태를 확인해야하는데

방법이 없음 낮은 프리퀀시의 틱으로 한다해도 모든액터가 프리뷰 레벨을 확인할 없는거고

그래서 에디터상에서 프리뷰 레벨을 변경할때 호출되는 함수나 이벤트를 찾아봄

 

 

일단 델리게이트 선언은 쉽게 찾았음 이름이 정직해서

World.h

 

DECLARE_MULTICAST_DELEGATE_OneParam(FOnActorSpawned, AActor*);

DECLARE_MULTICAST_DELEGATE_OneParam(FOnActorDestroyed, AActor*);

DECLARE_MULTICAST_DELEGATE_OneParam(FOnPostRegisterAllActorComponents, AActor*);

DECLARE_MULTICAST_DELEGATE_OneParam(FOnPreUnregisterAllActorComponents, AActor*);

DECLARE_MULTICAST_DELEGATE_OneParam(FOnActorRemovedFromWorld, AActor*);

DECLARE_MULTICAST_DELEGATE_OneParam(FOnFeatureLevelChanged, ERHIFeatureLevel::Type);

DECLARE_MULTICAST_DELEGATE_OneParam(FOnMovieSceneSequenceTick, float);

 

월드에 델리게이트_파람1 선언이 되있고 델리게이트를 받을 있게 처리만 하면되는거였는데..

 

일단 에디터모듈쪽에 등록하기로 생각하고

델리게이트 사용법을 전혀 몰라서 열심히 뒤져봄

 

FOnFeatureLevelChanged 이건 델리게이트 이름이고 뒤에 ERHIFeatureLevel::Type 이형식의 파라메터로 바인딩을 하면되는건 알겠는데 바인딩 하는방법도 모르겠어서 엔진 코드를 뒤져보니

 

FOpenColorIOEditorModule 이란 곳에서 비슷한걸 구현해둔걸 보게됨

 

 

FOnFeatureLevelChanged::FDelegate FeatureLevelChangedDelegate = FOnFeatureLevelChanged::FDelegate::CreateRaw(this, &FOpenColorIOEditorModule::OnLevelEditorFeatureLevelChanged);

    FeatureLevelChangedDelegateHandle = EditorWorld->AddOnFeatureLevelChangedHandler(FeatureLevelChangedDelegate);

 

 

이걸보니 델리게이트에 createrow add row 써서 브로드 캐스팅을 받을 함수를 등록을 하고

델리게이트를 월드의 브로드캐스팅 대상 멤버로 추가해주면 되는듯

 

아직도 약간 어렵긴하지만

결국 블루프린트의 이벤트 디스패쳐랑 비슷한 느낌으로 보면되는거같음

 

최종 함수는

 

void FTemppalEditorModule::StartupModule()

{

..

..

..

..

    FCoreDelegates::OnPostEngineInit.AddRaw(this, &FTemppalEditorModule::OnPostEngineInit);

    //@pts hidden Actor in Editor U_Es3_1 For ExcludeFormMobile

    FWorldDelegates::OnPreWorldInitialization.AddRaw(this, &FTemppalEditorModule::OnWorldInit);

    //@pts hidden Actor in Editor U_Es3_1 For ExcludeFormMobile

}

//@pts hidden Actor in Editor U_Es3_1 For ExcludeFormMobile

void FTemppalEditorModule::OnWorldInit(UWorld* InWorld, const UWorld::InitializationValues InInitializationValues)

{   if (InWorld && InWorld->WorldType == EWorldType::Editor)

    {

        WeakWorld = InWorld;

        FOnFeatureLevelChanged::FDelegate Delegate =

            FOnFeatureLevelChanged::FDelegate::CreateRaw(this, &FTemppalEditorModule::OnLevelEditorFeatureLevelChanged);

        FeatureLevelChangedDelegateHandle = WeakWorld->AddOnFeatureLevelChangedHandler(Delegate);

    }

}

void FTemppalEditorModule::OnLevelEditorFeatureLevelChanged(ERHIFeatureLevel::Type InFeatureLevel)

{

    UWorld* World = WeakWorld->GetWorld();

    if (!World) return;

    for (TActorIterator<AActor> It(World); It; ++It)

    {

        AActor* Actor = *It;

        if (Actor->bShouldBeExcludedFromMobile)

        {

            Actor->SetIsTemporarilyHiddenInEditor(InFeatureLevel <= ERHIFeatureLevel::ES3_1);

        }

    }

}

//@pts hidden Actor in Editor U_Es3_1 For ExcludeFormMobile - end

 

액터를 체크할때 뭔가 태그모음을 걸어서 태그 모음안의 액터만 처리할까도 했는데 어차피 에디터전용기능이고 모은 태그를 공유하려면 이것저것 만들어야할게 많아서 일단 여기서 마무리처리함

언리얼 나이아가라 대부분의 기능은 노드로 구현이 가능함 지버퍼나 스크린 데이터도

가끔 없는기능이나 불편한 기능이 존재해 노드를 추가할 필요가 있는데 나이아가라는 머터리얼처럼 간단히 추가할 없음

 

일정때문에 너무 급히 만들다보니 완전 디테일하게 파악하지 못하고 대충 이런 흐름을 따라 추가할수 있다 정도로만 보시면될듯합니다.

 

 

일단 모든 노드는 각자의 데이터인터페이스 클래스를 갖고 있음

플러그인으로 만드는것도 가능하다고 하지만 처음해보는거라

그냥 나이아가라 플러그인 안쪽에 파일을 추가함

 

 

Engine\Plugins\FX\Niagara\Source\Niagara\Classes\NiagaraDataInterfaceCheckPlatform.h

Engine\Plugins\FX\Niagara\Source\Niagara\Private\NiagaraDataInterfaceCheckPlatform.cpp

 

 

헤더

 

 

#pragma once

#include "NiagaraCommon.h"

#include "NiagaraShared.h"

#include "NiagaraPlatformSet.h"

#include "NiagaraDataInterface.h"

#include "NiagaraDataInterfaceCheckPlatform.generated.h"

UCLASS(EditInlineNew, Category="Performance", meta = (DisplayName = "CheckPlatform"))

class UNiagaraDataInterfaceCheckPlatform : public UNiagaraDataInterface

{

    GENERATED_BODY()

public:

    UNiagaraDataInterfaceCheckPlatform();

 

    //UObject Interface

    NIAGARA_API virtual void PostInitProperties() override;

    //UObject Interface End

public:

#if WITH_EDITORONLY_DATA

    NIAGARA_API virtual void GetFunctionsInternal(TArray<FNiagaraFunctionSignature>& OutFunctions) const override;

#endif

    NIAGARA_API virtual void GetVMExternalFunction(const FVMExternalFunctionBindingInfo& BindingInfo,

                                       void* InstanceData,

                                       FVMExternalFunction& OutFunc) override;

   

    NIAGARA_API void ExecIsMobile(FVectorVMExternalFunctionContext& Context);

   

    bool bIsMobile;

protected:

    NIAGARA_API virtual bool CopyToInternal(UNiagaraDataInterface* Destination) const override;

    //~ UNiagaraDataInterface interface

private:

};

 

 

소스

 

 

#include "NiagaraDataInterfaceCheckPlatform.h"

#include "NiagaraTypes.h"

//#include "NiagaraFunctionSignature.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(NiagaraDataInterfaceCheckPlatform)

//@pts NiagaraMobileOpt DataInterface

UNiagaraDataInterfaceCheckPlatform::UNiagaraDataInterfaceCheckPlatform()

{

}

 

void UNiagaraDataInterfaceCheckPlatform::PostInitProperties()

{

    Super::PostInitProperties();

    if (HasAnyFlags(RF_ClassDefaultObject))

    {

        ENiagaraTypeRegistryFlags Flags = ENiagaraTypeRegistryFlags::AllowAnyVariable | ENiagaraTypeRegistryFlags::AllowParameter;

        FNiagaraTypeRegistry::Register(FNiagaraTypeDefinition(GetClass()), Flags);

    }

}

 

#if WITH_EDITORONLY_DATA

void UNiagaraDataInterfaceCheckPlatform::GetFunctionsInternal(TArray<FNiagaraFunctionSignature>& OutFunctions) const

{

    {

        FNiagaraFunctionSignature Sig;

        Sig.Name = FName("IsMobile");

        Sig.bMemberFunction = true;

        Sig.Inputs.Add(FNiagaraVariable(FNiagaraTypeDefinition(GetClass()), TEXT("PlatformCheckSet")));

        Sig.Outputs.Add(FNiagaraVariable(FNiagaraTypeDefinition::GetBoolDef(), TEXT("Result")));

        OutFunctions.Add(Sig);

    }

}

#endif

 

 

void UNiagaraDataInterfaceCheckPlatform::GetVMExternalFunction(

    const FVMExternalFunctionBindingInfo& BindingInfo,

    void* InstanceData,

    FVMExternalFunction& OutFunc)

{

    if (BindingInfo.Name == FName("IsMobile") && BindingInfo.GetNumInputs() == 0 && BindingInfo.GetNumOutputs() == 1)

    {

        OutFunc = FVMExternalFunction::CreateUObject(this, &UNiagaraDataInterfaceCheckPlatform::ExecIsMobile);

}

}

 

bool UNiagaraDataInterfaceCheckPlatform::CopyToInternal(UNiagaraDataInterface* Destination) const

{

    if (!Super::CopyToInternal(Destination))

    {

        return false;

    }

    UNiagaraDataInterfaceCheckPlatform* DestinationTyped = CastChecked<UNiagaraDataInterfaceCheckPlatform>(Destination);

    DestinationTyped->bIsMobile = bIsMobile;

    return true;

}

 

void UNiagaraDataInterfaceCheckPlatform::ExecIsMobile(FVectorVMExternalFunctionContext& Context)

{

    VectorVM::FExternalFuncRegisterHandler<FNiagaraBool> OutValue(Context);

    //실제 디바이스에서 처리

#if PLATFORM_ANDROID || PLATFORM_IOS

    bIsMobile = true;

#else

    bIsMobile = false;

#endif

    //에디터 프리뷰용 처리

#if WITH_EDITOR

    if (UWorld* World = GetWorld())

    {

        ERHIFeatureLevel::Type FeatureLevel = World->GetFeatureLevel();

        bIsMobile = (FeatureLevel <= ERHIFeatureLevel::ES3_1);

    }

    else

    {

        // fallback

        ERHIFeatureLevel::Type FeatureLevel = GMaxRHIFeatureLevel;

        FeatureLevel = GEditor->PreviewPlatform.GetEffectivePreviewFeatureLevel();

        if (FeatureLevel)

        {

            bIsMobile = (FeatureLevel <= ERHIFeatureLevel::ES3_1);

        }

        else

        {

            UE_LOG(LogTemp, Warning, TEXT("FeatureLevel is Empty"));

        }

    }

#endif

    for (int32 i = 0; i < Context.GetNumInstances(); ++i)

    {

        *OutValue.GetDestAndAdvance() = FNiagaraBool(bIsMobile);

    }

}

 

 

UNiagaraDataInterface 상속받아 클래스를 생성하는데

함수 호출을

 

비긴 디폴트처럼 아예 곳에서 호출하는건 찾지 못해서 어쩔수 없이 체크 플랫폼 같은 형식으로 만들게됨

 

생성자 함수는 무조건 만들어주어야 하는것 같음 - 모름

 

UNiagaraDataInterfaceCheckPlatform::UNiagaraDataInterfaceCheckPlatform()

{

}

 

 

 

void UNiagaraDataInterfaceCheckPlatform::PostInitProperties()

{

    Super::PostInitProperties();

    if (HasAnyFlags(RF_ClassDefaultObject))

    {

        ENiagaraTypeRegistryFlags Flags = ENiagaraTypeRegistryFlags::AllowAnyVariable | ENiagaraTypeRegistryFlags::AllowParameter;

        FNiagaraTypeRegistry::Register(FNiagaraTypeDefinition(GetClass()), Flags);

    }

}

 

 

함수는 나이아가라에 프로퍼티로 데이터인터페이스를 등록해줍니다

뭔가 저기서(ENiagaraTypeRegistryFlags같은거) 수정을 하면 어디서든 등장할 있을거같은데 시간이 없어서 해보진 못했음

 

 

 

#if WITH_EDITORONLY_DATA

void UNiagaraDataInterfaceCheckPlatform::GetFunctionsInternal(TArray<FNiagaraFunctionSignature>& OutFunctions) const

{

    {

        FNiagaraFunctionSignature Sig;

        Sig.Name = FName("IsMobile");

        Sig.bMemberFunction = true;

        Sig.Inputs.Add(FNiagaraVariable(FNiagaraTypeDefinition(GetClass()), TEXT("PlatformCheckSet")));

        Sig.Outputs.Add(FNiagaraVariable(FNiagaraTypeDefinition::GetBoolDef(), TEXT("Result")));

        OutFunctions.Add(Sig);

    }

}

#endif

 

함수가 내가 추가할 함수의 시그니처를 만들어주는 함수 저기서 선언한 형태로 핀이나 이름을 설정할 있고 함수 바디는 다른곳에서 처리해줌..

 

 

 

void UNiagaraDataInterfaceCheckPlatform::GetVMExternalFunction(

    const FVMExternalFunctionBindingInfo& BindingInfo,

    void* InstanceData,

    FVMExternalFunction& OutFunc)

{

    if (BindingInfo.Name == FName("IsMobile") && BindingInfo.GetNumInputs() == 0 && BindingInfo.GetNumOutputs() == 1)

    {

        OutFunc = FVMExternalFunction::CreateUObject(this, &UNiagaraDataInterfaceCheckPlatform::ExecIsMobile);

}

}

 

함수가 vm에서 함수를 실행하게 해주는 함수이며 규칙도 동일함 시그니처 네임으로 확인하므로 여러 개도 될거같긴한데 테스트는 못해봄…

 

 

 

bool UNiagaraDataInterfaceCheckPlatform::CopyToInternal(UNiagaraDataInterface* Destination) const

{

    if (!Super::CopyToInternal(Destination))

    {

        return false;

    }

    UNiagaraDataInterfaceCheckPlatform* DestinationTyped = CastChecked<UNiagaraDataInterfaceCheckPlatform>(Destination);

    DestinationTyped->bIsMobile = bIsMobile;

    return true;

}

함수는 정확히 파악을 하지 못했음 함수가 없을때는 핀이 등록이 되지 않았음 그래서 뭔가 비슷한 형태의 노드를 찾다보니 죄다 함수가 있어서 보니 내부에서 생성한 규칙을 글로벌로 처리해주는느낌이어서 형식에 맞게 고쳐주니 노드에서 보이는것 같음

기능이 함수에 있다고 생각이되는데 페어 함수인거같긴함

 

 

void UNiagaraDataInterfaceCheckPlatform::ExecIsMobile(FVectorVMExternalFunctionContext& Context)

{

    VectorVM::FExternalFuncRegisterHandler<FNiagaraBool> OutValue(Context);

    //실제 디바이스에서 처리

#if PLATFORM_ANDROID || PLATFORM_IOS

    bIsMobile = true;

#else

    bIsMobile = false;

#endif

    //에디터 프리뷰용 처리

#if WITH_EDITOR

    if (UWorld* World = GetWorld())

    {

        ERHIFeatureLevel::Type FeatureLevel = World->GetFeatureLevel();

        bIsMobile = (FeatureLevel <= ERHIFeatureLevel::ES3_1);

    }

    else

    {

        // fallback

        ERHIFeatureLevel::Type FeatureLevel = GMaxRHIFeatureLevel;

        FeatureLevel = GEditor->PreviewPlatform.GetEffectivePreviewFeatureLevel();

        if (FeatureLevel)

        {

            bIsMobile = (FeatureLevel <= ERHIFeatureLevel::ES3_1);

        }

        else

        {

            UE_LOG(LogTemp, Warning, TEXT("FeatureLevel is Empty"));

        }

    }

#endif

    for (int32 i = 0; i < Context.GetNumInstances(); ++i)

    {

        *OutValue.GetDestAndAdvance() = FNiagaraBool(bIsMobile);

    }

}

 

바디 기능을 쓰기위해 인터페이스를 뚫는 과정이었고 내용은 모바일 체크임

실제로 기능자체라기보다는 나이아가라에 원하는 기능을 추가 있는 인터페이스의 구조나 흐름을 보기위해 기록은 남김

케릭터 라이트 그림자의 강도등을 라이팅이 아닌 별도의 옵션으로 세부 제어할 있도록 렌더링 기능 개선 개발

 

콘솔파라메터를 세이더 내부에 연결해 세이딩 모델마다 연산하는 강도를 제어할수있도록 처리함

'unreal > UnrealRendering' 카테고리의 다른 글

[Unreal_Rendering]ToonShading  (5) 2024.06.18
[Unreal_Rendering]HeightFog 개선  (0) 2024.06.12
[Unreal_Rendering]ToneMapper 수정  (0) 2024.06.12

> 방향으로 개선 진행

기본 머터리얼은 거의 동일한 상태

최초 헤어가 너무 모직같고 머릿결보다는 같다는 피드백을 받아

부드럽고 결이 약간 뭉쳐져 있는 방향으로 개선

 

이후 각자의 결을 살릴수 있는 방향(모직같지 않은 느낌으로) 덩어리감을 임의로 넣을 있도록 개선

 

세부 내역

음영을 텍스쳐를 이용해서 강제  엠비언트 오쿨루전 설정
텍스쳐에서
머터리얼 핀으로 음영처리를 있도록(결의 강화 덩어리감 처리) 처리

 

세이더 내부에서는 해당 데이터를 받아서 음영을 연산음영대신 텍스쳐데이터로 처리하도록 변경

Engine/Shaders/Private/Lumen/LumenMaterial.ush

 

Out.MaterialAO = GBufferData.GBufferAO;

    //@pts lumenhair

    Out.ShadingID = GBufferData.ShadingModelID;

    if(GBufferData.ShadingModelID == SHADINGMODELID_HAIR)

    {

        Out.GBufferData.GBufferAO = GBufferData.GBufferAO;

        Out.MaterialAO = GBufferData.GBufferAO;

        Out.DiffuseIndirectSampleOcclusion = GBufferData.GBufferAO;

    }

    else

    {

        Out.MaterialAO = GBufferData.GBufferAO;

        GBufferData.DiffuseIndirectSampleOcclusion;

    }

+ Recent posts