[UE4]如何使用Visual studio Graphics Debugger來為shader除錯

posted in: UnrealEngine, 未分類 | 0

基本上官方推薦的shader除錯流程是使用Renderdoc這個Plugin來進行: https://github.com/Temaran/UE4RenderDocPlugin 這個Plugin在4.17的時候就已經整合進到Engine Plugin中了, 只要照著上面網址中的教學進行就能夠開起來。 只是,在用Visual Studio的時候會發現,裡面也有一個自帶的Graphics Debugger: 直接按下這個按鈕之後,引擎會直接噴下面的錯誤訊息: DX11 Feature level 10.0 is required to run the engine. 那麼我們到底該怎麼使這個工具呢? 我們需要修改ConsoleVariables.ini這個檔案(請手動新增在專案的Config資料夾下), 並插入以下內容: [Startup] r.GraphicsAdapter=0 0代表的就是使用第一個找到的Graphics Adapter,其在引擎中的詳細宣告如下: static TAutoConsoleVariable CVarGraphicsAdapter( TEXT(“r.GraphicsAdapter”), -1, TEXT(“User request to pick a specific graphics adapter (e.g. … Continued

[UE4]淺談UE4 Modules

對於大型軟體系統而言, 各別功能之間的相依性控管一直都不是個簡單的問題。 為了減少程式碼在管理上的複雜度, 導入Module這個概念,將整個系統拆分成各別獨立且互相緊密合作的單位, 變成了一個非常常見的設計手法。 其實就目前而言,C++還沒有一個真正意義上的「Module System」, 雖然在 C++20[1] 的標準中已經有加入Module相關機制的草案, 但很顯然的,UE4所使用的Module機制並不是對標準庫中該草案的實現。 作為一個走在技術前端的引擎,很多功能當然不會等到標準庫穩定後才導入。 UE4所實現的這套Module System並不依賴於編譯器的實作, 相對的,它在現有的C++標準庫的基礎上設計了自己的一套跨平台建構系統,Unreal Build Tool(UBT)。 這套建構系統,不僅可以控管每個Module載入的時機,並且也擁有許多編譯優化機制。 為了正確理解UE4中這套Module System的運作方式, 首先,我們必須要先理解到底什麼是「Module」。 在抽象概念上,所謂的Module,其實就是一些功能的「集合」。 在C++中,我們可以想成它是一堆 Translation Unit(或稱Compliation unit) [2] 所產生的.obj檔的集合;而這些.obj檔的集合,就是UE4中所定義的Module。   接著,UBT根據不同的編譯環境有以下幾個選擇: 將Module所包含的.obj檔編譯進到最後的.exe檔中。 將Module所包含的.obj檔做成Static Library(.lib)。 將Module所包含的.obj檔做成Dynamic Library(.dll)進而實現在Runtime時期動態載入功能。 UE4在預設情況下,若編譯的TargetType是Editor, 則TargetLinkType會設成Modular,意即所有的Module都會被做成(.dll); 若是TargetType是其他的型態,引擎則會視所編譯的Module是PluginModule還是GameModule進行不同的動作。 前者會被做成(.lib),後者則會直接編譯連結進到最後的exe檔中。 為什麼Editor要特別設定成Modular形態? … Continued

認識Editor環境與UE4檔案命名系統

posted in: 未分類 | 1

UE4所提供的Editor非常強大,裡面的功能非常的多,實在不是在一個章節中有辦法全部介紹完畢。其實要熟悉編輯器的介面最快的方法,就是根據需求再去找出功能對應的位置。本節並不試圖在這裡就去解釋所有的功能,相對的,這裡會列出一些初學者常用區塊。 在打開初始專案後者先引擎會先載入一個預設的map,見Figure 1.5.1,該map儲存於${EngineVersion}\Engine\Content\Maps\ Templates\Template_Default.umap底下。 Figure 1.5.1 引擎預設載入的map:/Engine/Maps/Templates/Template_Default,其實體路徑存在於${EngineVersion}\Engine\Content\Maps\ Templates\Template_Default.umap。 A區:基本上會根據所選擇的工具會有不同的內容,預設是顯示引擎中可以放到Level中的Actor。 B區:為editor常用的一些工具列,最常用的按鈕是按下Play後,運行被稱為PIE(Play In Editor)模式。 C區:主要用來調整視角光影或者是一些開發時除錯用的資訊,例如要不要顯示mesh的collision範圍,或者是特定的post process效果……等等。 D區:一些編輯關卡時有用的工具,例如該actor的編輯模式是要移動、旋轉還是放大,移動或旋轉時操作一次要更動多少數值,以及編輯時camera移動的速度要多快。這邊自己與其用文字描述,不如自己操作一次會比較有感覺。 E區:顯示目前關卡上置放的Actor,可以讓我們用來視覺化對該actor進行編輯。 F區:顯示現在的關卡名字。 G區:顯示目前關卡上置放的Actor,跟E區不同的是,這邊是顯示所有關卡上的instance。 H區:讓我們一次將所有的更動作儲存,由於目前引擎的存檔機制還不是很穩定,有時候直接關掉引擎時跳出的儲存視窗不會成功的將結果保存起來,因此這個按鍵就發揮了很大的功用。 I、J、K區:Content Browser,用來顯示目前我們可用的素材。在I區顯示Folder分別會對應到以下幾個實體路徑: Game:${PROJECT_NAME}\Content,顯示我們import到專案中的assets。 C++ Classes\${PROJECT_NAME}:${PROJECT_NAME}\Source\${PROJECT_NAME},顯示我們所實作的UClass。 若是我們在K區將Show Engine Content選取後,我們就可以看到Figure 1.5.2的內容: Figure 1.5.2 在K區將Show Engine Content選取後可以看到Engine Content Figure 1.5.1所提到的/Engine/Maps/Entry,我們可以在Engine Content/Maps下找到。到這裡我們應該可以看出來Unreal內部有機制將實體目錄對應到其內部的檔案命名系統。其中: /Content/:對應到的是${PROJECT_NAME}\Content。 /Engine/:對應到的是${EngineVersion}\Engine\Content\。 /Script/:對應到的是${PROJECT_NAME}\Source。 … Continued

結合boost.log跟Unreal Engine 4的log系統

最近在研究怎麼把boost跟UE4做結合使用,目前已經成功的將一些好用的boost library應用在專案上了,就先來整理一下相關該注意的技術事項吧。 首先我嘗試導入的是boost的log機制,雖然UE4本身已經有LOG系統了,但稍微survey了一下,看起來其實還是不太完整,而且log寫起來其實還蠻費勁的;如果能把boost.log導進來的話,不僅輸出log的時候會更方便,而且又能夠利用boost.log本身上提供的許多強大的功能。 其實boost.log還蠻容易跟其他引擎做結合的,我們只需要寫一個backend,並將其所綁定的sink加入到boost.log系統裡面就行了。而這個backend要做的事情也很簡單,它只需要負責把傳進來的訊息再原封不動的傳給UE4原本的log系統。聽起來是不是很簡單?先讓我們來看一下下面這段code: https://gist.github.com/dorgonman/fdab8f1be4a11a4a4fbc 把sink加入到log系統的方式如下: typedef boost::log::sinks::synchronous_sink<HorizonLogBasicFormatedBackend> HorizonLogSink; boost::log::core::get()->add_sink(sink); 紅色的部份是我們自己寫的backend,其實作如下: https://gist.github.com/dorgonman/3f56b82a8116bddb3425 這個backend留有一個接口: inline void setLogMessageImplemen(HorizonLogImpFunc_t&& impl); 目的就是留一個log的實作方式給引擎方去設定,我們需要做的就是從UE4丟一個std::function到backend就行了。設定方式如下: https://gist.github.com/dorgonman/0db4138c2cee95b51582 然後由於UE4中的check macro跟boost中的有衝突,因此在include boost 相關的header之前需先做下面這件事: #pragma push_macro(“check”) #undef check //include your boost header here #pragma pop_macro(“check”) 接下來我們就可以很方便的使用boost所提供的log機制了: https://gist.github.com/dorgonman/575f2e4a3c78621bcff8 只是目前的機制只能用在64位元的版本中,不知道為什麼當運行起32位元的時候總是會在下面這行code crash: if (_Myostr.rdbuf() … Continued

[讀書筆記]Universal References in C++11 part 3: 記憶體管理以及Rule of Three(Five)

    [insert page=’338′ display=’link’] 上一篇主要介紹了rvalue reference的概念,以及它導入用來解決無法區分lvalue reference以及暫存物件之間的copy問題。基本上這些操作的本質,其實也就是怎麼用更有效率、更簡單的方法去控管我們所使用的資源而已。──記憶體管理,一直是C++程式設計中一個非常重要的課題。 一個最常被提到的準則便是RAII的概念。何謂RAII?全名Resource Acquisition Is Initialisation,意即所有接下來這個物件所會用到的資源,在建構階段就已經全部建立完成。例如檔案的開啟、變數的初始化或記憶體配置。但這句話只說了一半,另外一個對應概念是Resource Release Is Destruction (RRID),意即在解構階段必須將所有要來的資源還回去。 自己new出來的要記得delete,之前開檔案要記得關。它是一種資源所有權管理的概念,每個物件要在自己的生命週期內管理自己擁有的資源;它也是一個設計的大原則,用來提醒程式設計師要記得將不要的資源釋放出去。不然帶來的後果,便是系統的不穩定或是直接崩潰。 可是我們該怎麼在C++中正確的實作RAII、RRID呢?只要在建構子跟解構子中做完對應的初始化以及釋放的動作就行了嗎?答案是,對,可是也不對。正確的解答應該要看我們對於這個類別在功能性上的設計與期待。若是該物件有將別的物件拷貝一份到自己身上的需求,則需要思考的是我們要進行的是deep copy、shallow copy還是將別人身上所管理的資源move到自己身上。嗯?這個不是上一篇所提到東西嗎?──沒錯,只是上一篇在程式碼的實作上並沒有符合我們對於一個類別在資源管理機制上的期待。一份完整的實作,必須要遵循 Rule of Three的設計準則:若是設計師有實作下列任何一個function,則其他的function都必須要有合適的實作: class Widget{ public: /** Copy constructor */ Widget(const Widget& other){ memberwiseCopy(other); } /** Destructor */ ~Widget(){} /** … Continued

[UnrealEngine4] Plugin System學習筆記

posted in: 未分類 | 0

在進行本文之前,推薦先閱讀以下官方文檔: https://wiki.unrealengine.com/An_Introduction_to_UE4_Plugins https://docs.unrealengine.com/latest/INT/Programming/Modules/API/index.html 本文開始: 對於UnrealEngine而言,其實Plugin也是歸於FModuleManager的管理之下。 跟一般Module不同的地方在於其多了${PluginName}.uplugin, 用來描述並管理這個Module的用途,一個簡單的Plugin的結構如下: 其中MyPlugin.uplugin中的檔案內容如下 我們可以看到,在這個MyPlugin之中我建立了3個Module,並在MyPlugin.uplugin之中將『MyPlugin』的Type設為Runtime、『MyDeveloperPlugin』設為Developer、『MyEditorPlugin』設為Editor。 其中Runtime會在任何情況下都會載入、Developer是除了Shipping的build之外都載入、 而Editor如其名,只會在編輯器模式下載入(通常是在做工具時使用)。 而LoadingPhase則是在描述該Module的載入時機點,若沒指明則為Default。如下圖,詳細行為請參考源碼: Engine/Source/Runtime/Projects/Public/ModuleDescriptor.h。 另外,值得注意的是一個跟Plugin同名的Module是必要的,不然該Plugin將會無法編譯。 (在上面的Case中我們可以看到MyPlugin/Source/下面有一個MyPlugin,再提醒一次,同名Module是必需的。) 在導入完Plugin之後,接著想會要在我們的遊戲中使用。 首先,必須要在我們專案的的Build.cs中加入以下指令,不然會找不到該module的標頭檔: 請注意,在使用任何外部Module之前,必須要先檢查該類別有沒有export給外部的module使用,在unreal engine中,是用以下的宣告型式: class ${UPPERCASE_MODULE_NAME}_API 下面則為本文中MyPlugin的例子:   class MYPLUGIN_API FMyPlugin : public IModuleInterface class MYDEVELOPERPLUGIN_API FMyDeveloperPlugin : public IModuleInterface class MYEDITORPLUGIN_API FMyEditorPlugin : public … Continued

[C/C++]移除編譯依賴的小技巧

posted in: 未分類 | 0

相信有不少人有這種經驗:如果所處理的是一個非常大型的專案,常常更改一些小東西就要等個10幾20分的編譯時間。那麼我們該怎麼處理這個問題呢? 以下內容見exceptional c++ item26 ~ item 28: // file x.h class X { // public and protected members private: struct XImpl;// a pointer to a forward-declared class XImpl* pimpl_; // a pointer to a forward-declared class }; // file x.cpp … Continued

[C/C++] [template] concept check的簡單實作

posted in: 未分類 | 0

  可搭配參閱上篇文章:  [insert page=’198′ display=’link’]   concept check導入目的,是為了讓template所產生的編譯錯誤能夠及早在概念層中就被發現,而不是等程式執行到問題發生的那一行才一次性的爆發出template具現化的過程。 例如下面的例子(出自於《C++ Templates全覽》): #include <iostream> using namespace std; template <typename T> void clear (T p){ *p = 0; // assumes T is a pointer-like type std::cout << p << std::endl; } template <typename … Continued

[Jenkins][xcode] User interaction is not allowed

posted in: 未分類 | 0

http://stackoverflow.com/questions/577750/running-xcodebuild-from-a-forked-terminal/581002#581002 solution :  ‧Open the Keychain Access  ‧Right click on the private key  ‧Select "Get Info"  ‧Select "Access Control" tab  ‧Click "Allow all applications to access this item"  ‧Click "Save Changes"  ‧Enter your password  ‧Enjoy

[git] cygwin + git + github + openssh + jenkins除錯過程記錄

posted in: 未分類 | 0

  1.安裝cygwin,並將Devl跟shell打勾 2.使用openSSH來產生public/private key pair:在cygwin shell底下打入ssh-keygen,之後在C:\Users\yourname\.ssh下會產生id_rsa跟id_rsa.pub二個檔案 3.將id_rsa.pub的內容複製下來,丟到github=>account setting=>ssh keys 4.如果在安裝tortoiseGit的時候沒有選擇openSSH,則:右鍵=>tortoisegit=>setting=>network=>SSH client的選徑選成C:\cygwin\bin\ssh.exe即可 5.在github上創建一個專案,但要pull下來的時候卻遇到Error: Permission denied (publickey):將C:\Users\yourname\.ssh目錄複製到C:\cygwin\home\yourname底下 6.打開cygwin shell 執行ssh -vT git@github.com可以測試跟github的連接。 7.此時應該可以成功的進行pull 8.安裝jenkins的時候,如果打不開的話,則下netstate –no檢查8080 port是否被佔用 通常有skype的話就會發生此情形,解決辦法是先將skype關掉再打開之後,skype就會自己去找其他的port使用   9.在設定jenkins時,如果git路徑指向C:\cygwin\bin\git.exe,則jenkins會去讀取C:\cygwin\.ssh底下的private key。此時我們必須將key複製到此目錄下才行。(一開始設git repositories的時候會產生ailed to connect to repository : Command “C:\cygwin\bin\git.exe ls-remote -h xxxx returned … Continued