UE4の勉強記録

UE4の勉強の記録です。個人用です。

UE5の勉強 -映像作品としてのLandscapeを作成する-

1. 今週の予定

このBlogは結構重要な内容がまとめられているんですが、読み直さないとその重要な内容を発展させる事が出来ない事に気が付きました。

後で検索すると、同じ事を三回位言ってその後何もしてないって事がありました。

ので先週のBlogを読み直しながら今週の予定を決定します。

今週は以下の2つの勉強について検討もします。

1.1 映像作品としてのLevelの作成

この後、更に映像を改良して一応音ありの映像が出来ました。

その内容をまとめます。

後、3D Gaussian Splattingで生成したPlyをUEに配置し、そこにStatic Meshを配置した場合、Static Meshの影が映らない問題はあまり重要ではなかったです。

でこれは一応調査はする事にします。

1.2 AIの勉強

Jeremy Howard氏の Practical Deep Learning for Coders: Lesson 1 [1]の宿題の続きをやります。

まず教科書の続きを読みます。

後、Jupyterについて調査します。

Kaggleとどちらを使用すべきかを決定します。

教科書をJupyterで読めるらしいのでその辺はしっかり調べる事にします。

そしてKaggleかJupyterで宿題をやってみます。

1.3 Materialの勉強

先週、Pwnisher氏のUnreal Engine Materials in 6 Levels of Complexity [2]の実装を行いました。

そしてこのまま勉強して終わりにしてしまうと今までと同じになってしまうから、ここからどうやって発展させていくのかを考えました。

これを今週はやります。

Mega ScanでDownloadしたSurfaceのAssetのTextureは全部同じです。

それらに使用されている元のMaterialの実装をPwnisher氏のMaterialの良い部分を追加して改良します。

後はBen Cloward先生の勉強か。

これも一応やる事にします。

1.4 Gaeaの勉強

今週からBuildについてのTutorialを作成します。

今週はBuildについて勉強をします。

1.5 UE5.4の新しい機能について

2024-05-05のBlogには以下の勉強をすると書いていました。

それで本来は先週はOfficial Android Support for Unreal Engine Virtual Camera [3]を実装する予定だったんですが、諸事情によりUnreal Engine 5.4 Plant Growth Effect Tutorial In Under 5 Mins [4]を勉強しました。

今週はどちらかを実装します。

更に公式のSequencer Editor [5]とSequencer EditorCine Camera Actor [6]の勉強も行います。

1.6 Houdiniの勉強

Houdini 19 - Wall Tool 13[7]の実装を行います。

1.7 UEFNの勉強

Pi Equals Three氏のTutorialを勉強します。

1.8 DirectX12の勉強

Lötwig Fusel氏のD3D12 Beginners Tutorial [D3D12Ez]は Creating a Window | D3D12 Beginners Tutorial [D3D12Ez] [8]の次の10分を実装します。

DirectX 12の魔導書」の勉強は、「4.11 三角形ポリゴンを四角形にしてみる」の「4.11.2 Indexを利用する」を勉強します。

2. 映像作品としてのLevelの作成

2.1 先週の更にやった内容

先週開いている時間を利用して音をWav FileとしてExportし、それをDavinci Resolveで映像と合成しました。

更にDavinci ResolveのEffect機能を利用して映像を更に加工しました。

結果です。

youtu.be

これは完成度が高いので公開する事にします。

題は、

Unreal Engine 5 + 3D Gaussian Splatting(Luma AI)_Test1 自転車とドラゴン

とします。

Descriptionには

撮影した映像を元にLuma AIでGaussian Splattingを作成しました。

そのDataをUnreal Engine 5にImportし3D Modelと組み合わせてVFXな映像を作成しました。

ただしこの時点では映像は以下の点がおかしく写っていました。

  • Dragonが背景から浮いて見える
  • 背景の建物が歪んでいる
  • Dragonの影が地面に写らない

更にその映像をDavinci ResolveでEffectを追加するなどの編集をして、それらの欠点が目立たないようにしました。

と記す事にします。

Descriptionの英訳です。

Deep Lで直しました。

Gaussian splatting was created by Luma AI based on the video footage taken by me.

The data of Gaussian splatting was imported into Unreal Engine 5 and combined with a 3D model to create a VFX video.

However, at this point, the following points were not correct in the video.

  • The dragon appears to float out of the background.
  • The buildings in the background are distorted.
  • Dragon's shadow does not appear to be on the ground

We further edited the footage in Davinci Resolve, including adding Effects, to make these flaws less noticeable.

Copilotで文法のCheckをおこないました。

以下のようになりました。

Gaussian Splatting was created by Luma AI based on video footage. The data was imported into Unreal Engine 5 and combined with a 3D model to create a VFX video.

However, at this point, the following issues were observed in the video:

  • The dragon appears to float out of the background.
  • The buildings in the background are distorted.
  • The dragon’s shadow does not appear to be on the ground.

We further edited the footage in DaVinci Resolve, including adding effects, to make these flaws less noticeable."

うーん。

Float outって浮いてるって意味でした。これは直訳になってしまっていますね。

Video FootageってVideoの事なのか?

Appear to be on the groundというと地面には現れなかった。と言う意味になって地面以外には影があると受け取られかねない。と思います。

後、自分で撮影した映像を元にGaussian Splattingを作成したという説明が抜けています。

しかしAI凄すぎます。

通訳、翻訳業は完全に廃業になりますね。

更にDeep Lでこの英語を日本語に訳してみました。

ガウス・スプラッティングは、ビデオ映像を基にLuma AIが作成しました。このデータをUnreal Engine 5にインポートし、3Dモデルと組み合わせてVFX映像を作成しました。

しかしこの時点で、映像に以下のような問題が確認されました:

  • ドラゴンが背景から浮いているように見える。
  • 背景の建物が歪んでいる。
  • ドラゴンの影が地面に映っていない。

これらの欠点を目立たなくするため、エフェクトの追加を含め、DaVinci Resolveで映像をさらに編集しました。"

最初の日本語です。

撮影した映像を元にLuma AIでGaussian Splattingを作成しました。

そのDataをUnreal Engine 5にImportし3D Modelと組み合わせてVFXな映像を作成しました。

ただしこの時点では映像は以下の点がおかしく写っていました。

  • Dragonが背景から浮いて見える
  • 背景の建物が歪んでいる
  • Dragonの影が地面に写らない

更にその映像をDavinci ResolveでEffectを追加するなどの編集をして、それらの欠点が目立たないようにしました。

この最初の文章を少し直します。

自分で撮影した映像を元にLuma AIでGaussian Splattingを作成しました。

そのGaussian SplattingをUnreal Engine 5にImportし3D Model(Dragon)と組み合わせてVFXな映像を作成しました。

ただしこの時点では映像は以下の点がおかしく写っていました。

  • Dragonが合成したのがはっきり分かる
  • 背景の建物が歪んでいる
  • Dragonの影が写らない

更にその映像をDavinci ResolveでEffectを追加するなどの編集をして、それらの欠点が目立たないようにしました。

これをもう一回翻訳します。

Deep Lの翻訳です。

 I created Gaussian Splatting with Luma AI based on the footage I shot.

The Gaussian Splatting was imported into Unreal Engine 5 and combined with a 3D model (Dragon) to create a VFX video.

However, at this point, the following points were not correct in the video.

  • It is clearly visible that the Dragon was composited.
  • The buildings in the background are distorted.
  • Dragon's shadow is not captured

I further edited the footage in Davinci Resolve, adding Effects and other edits to make those flaws less noticeable.

これをCopilotで校正します。

The Gaussian Splatting was imported into Unreal Engine 5 and combined with a 3D model (Dragon) to create a VFX video.

However, the following issues were observed:

  • The Dragon appears composited.
  • Background buildings are distorted.
  • The Dragon’s shadow is missing.

I further edited the footage in DaVinci Resolve, minimizing these flaws.

今度は完璧でしょう。

この文章をDeep Lで日本語に訳しました。

ガウス スプラッティングをアンリアル エンジン 5 にインポートし、3D モデル (ドラゴン) と組み合わせて VFX ビデオを作成しました。

しかし、以下の問題が発生しました:

  • ドラゴンが合成されて見える。
  • 背景の建物が歪んでいる。
  • ドラゴンの影が欠けている。

さらにDaVinci Resolveで映像を編集し、これらの欠点を最小限に抑えた。

後は合成されて見えるの訳がCompositedであっているかを調べます。

調べても分からないのでCopilotに質問しました。

2つの別のFilmを合成する事をCompositionと呼ぶそうです。

読み直してみるとCopilotの英文は重要な情報まで削ってしまっています。

Deep Lの訳を一寸だけ加工して載せる事にします。

Gaussian Splatting is created with Luma AI based on the footage I shot.

The Gaussian Splatting was imported into Unreal Engine 5 and combined with a 3D model (Dragon) to create a VFX video.

However, at this point, the following points were not correct in the video.

  • It is clearly visible that the Dragon was composited.
  • The buildings in the background are distorted.
  • Dragon's shadow is not captured

I further edited the footage in Davinci Resolve, adding Effects and other edits to make those flaws less noticeable.

公開しました。

2.2 Luma AIのGaussian Splattingに影を追加する方法を調査する

影が出る方法が判明しました。

Luma AIのDownloadに行くと以下のように

Gaussian SplatとLuma Fieldの2つのDownloadがあります。

Gaussian Splat からDownloadすると以下のPly FileがDownloadされます。

Luma FieldからDownloadすると以下のluma FileがDownloadされます。

このLuma Fileは影を追加する事が出来ます。

正し以下に示した様にLuma FileからUEにImportした3Dは映像がブレます。

youtu.be

ここから調整したらこのブレが直るのかどうか不明です。

今週出来るのはここまでです。

ので来週以降試したい事を以下にまとめておきます。

  • ブレは直るのか
  • ピントを自転車に合わせるには
  • 影を調整する
    • 色を薄くする(Skylight、Directional Lightの調整)
    • 背景の影と一致させる

以上です。

3. AIの勉強

今週は一寸用事が出来てあまり勉強出来なくなってしまったので、出来るだけやる事にします。

3.1 Jeremy Howard氏のTutorialを勉強

3.1.1 教科書の続きを読む

<What Is a Neural Network?>

これの意味がよく分からなかったです。

YouTubeで検索したら沢山、Neural Networkについて説明している動画が出て来ました。

一端読んで、やっぱり意味が分からなかったらこれらの動画を見るようにします。

前回読んでよく意味が分からなかった理由が分かりました。

Checkersと言う言葉が最初に出て来ますが、これは以下のGameを指す言葉でした。

このGameで勝つためのProgrammingの話を最初にしていました。

このGameを知らなかったから意味が分からなかった。

今度は理解出来ました。

まずこのCheckersのようなGameならModelをどのように作成するのかは何となく想像出来ます。

幾つかの戦略をModelに組み込んで、状況によってどの戦略を選択するのかを選択出来るようにします。

しかしImageを認識したり、Textを読み込むためのModelはどうやって組んだらいいんでしょうか?

そのためのModelがNeural Networkです。

そしてそのModelのWeightをよりよくするための調整方法がstochastic gradient descent (SGD)になります。

そんだけでした。

ここではNeural Networkやstochastic gradient descent (SGD)が具体的にどうやっているのかについての説明は全く書いてなかったです。

色々なModelがあり、そのModelの一つがNeural Networkである事は先週の段階で推測していました。

理解したら別に特別重要な話をしているわけではなかったです。

<A Bit of Deep Learning Jargon>

ここはDeep Learningで使用される専門用語の簡単な解説がしてありました。

以下にそれらの専門用語をまとめます。

<<Architecture>>

Modelの事を言う場合と、Modelを関数として表したものを言う場合の2通りがあるそうです。

<<Parameters>>

Weightの事だそうです。

これは説明されなくても分かります。

<<Predictions>>

PredictionsはLabelを使用しない独立した変数を使用して計算されたものを指すそうです。

これの意味はまだ完全には納得出来ないですね。

ここで言うLabelは犬とか猫を指すそうです。

それを使用しないってどういう事何でしょう。

更に、学習が終わったModelの事もPredicitionsと呼ぶそうです。

<<Loss>>

Predictionsがどれだけ正確な解答が返せるのかを測定する事をLossと言うみたいですね。

でもこれ後の説明だと一寸違う使い方をしているみたいな気もします。

<<>>

その後で以下の図が紹介されていました。

これを見るとModelがArchitecture、WeightがParameterになっています。

この部分は名称が変わっただけです。

この後、特定のParameterを持つModelが完成する訳ですが、それをPredictionsと呼んでいます。

それにLabelを追加して結果の成否を検証しています。

この部分がLossですね。

そのLossの結果からParameterを調整しています。

うーん。

まあそれぞれの専門用語の解釈はそれなりにあっているでしょう。

<Limitations Inherent To Machine Learning>

ここではMachine Learningの限界について簡単な説明をしていました。

DataにはImageだけでなくそのImageに正しいLabelがされている事が必要です。

このDataが無いとModelを作成するためのInputをする事が出来ません。

そして正しくLabelされたDataはあまり無いです。

InputされたDataからPatternを抽出するだけです。提供されたDataに偏りがあった場合は直しようがありません。

つまりこの方法では正解を予測する事は出来ても、お勧めの行動を決定する事は出来ません。

だいたいこんな感じでした。

この話の中で特に重要だと私が思うのは「この方法では正解を予測する事は出来ても、お勧めの行動を決定する事は出来ない。」と言う部分です。

この部分は、具体的な例を用いて詳しく説明されていました。

それはネットショッピングのお勧め欄の表示です。

これだいたい既に知っている商品やもしくは前に買ったことのある商品しか出て来ません。

優れた店員だったら、この顧客なら今度販売された新商品も興味があるはずだ。と推測してその新商品をお勧めしますが、Machine learningはそういう新商品が顧客が興味を持つかどうかの判断をする事は出来ない。

とありました。

勿論、それが出来るModelもあるそうですが、基本的にはPredictionしか出来ない。そうです。

うーん。

そう言う意味で「この方法では正解を予測する事は出来ても、お勧めの行動を決定する事は出来ない。」って言ってたの。

私はてっきり、Machine Learningの予測を元に行動を決定しても最適解にならない。って意味だと解釈していました。

何て言うか、こんなImageです。

今日はどんな予定で行動するのがBestかを生成AIに聞く訳です。

「生成AIが今日は休日ですので、午前中は喫茶店に行って読書、午後から公園を散歩したらどうでしょうか。」とお勧めの行動を答えます。

それを聞いてその通りに行動しようかと思ったら、喫茶店から帰ってきたらで眠くなってしまって公園には行かずに寝てしまいました。

夜、Newsを見たら、その公園に雷が落ちて大けがした人も出た。とやっていました。

結果的には公園に行かなくて良かった。

みたいな感じです。

うーん。

でもこの2つって原理的には同じ気もします。

それはInputされたDataが偏っている。つまり全部のDataがInputされてないから起きる偏差を表している気がします。

どうでしょうね。

<How Our Image Recognizer Works>

ここは具体的にImageを識別するための実装の仕方を説明しています。

何でこんな事を今更。と思ったらそれはLectureを見た後だからであって、この教科書だけで勉強している人はここで初めてFast.aiのCodeを勉強する事になる訳です。

まずImageの識別をするために必要なLibraryをImportします。

次に以下のCodeでFast.aiにあるDataをDownloadします。

ここで言うDataとはImageとそれにつけられたLabelを指しているはずです。

次のCodeです。

これはIs_Cat()関数を作成しているようです。

XにはどんなTypeが代入されるのか不明ですが、そのTypeはisupper()というMethodは持っているのは分かります。

教科書にはこの関数の機能を以下のように解説していました。

うーん。

xのClassが分からないと何をしているのかCodeから推測するのは無理ですね。

この説明を信じるしかありません。

次のCodeです。

このCodeはLectureの勉強で散々やりました。

Labelの名前を指定するのに先程のIs_Cat()関数が使用されています。ただしParameterはここでは指定していません。

これはPythonの仕様なのか、それともここでは関数だけ指定すればいいのか、うーんよく分かりません。

何とこの最後のParameterは使用するTransformerを指定していました。

生成AIの動画を見てるとTransformer、Transformerと呪文のように唱えていましたが、一体何の事かと思っていました。

既に一部とは言え勉強していたとは。

ここではTransformerについては以下の説明がありました。

TransformerとはTraining中に適応されるCodeの事だそうです。

ここではItem_tfmsを使用していました。

過去のBlogを確認したらLectureでもItem_tfmsを使用していました。

ClassificationとRegressionの違いについてのTipもありました。

ClassificationはClassつまり犬とか猫とかをPredictするためのModelでRegressionは温度や場所などの数字を予測するためのModelだそうです。

このTipの後に先程のIs_Cat()関数で何をやっていたのかの説明がありました。

まずIs_Cat()関数で使用されているXはFile名でした。Fast.aiではFile名の最初の文字は猫なら大文字、それ以外なら小文字になっています。

Isupper()関数は、そのFile名の最初の文字が大文字かどうかを調べて大文字だったらTrueを返す訳です。

元々File名が大文字になっているのは猫なので猫のFileがTrueを返すようになります。

valid_pct=0.2についても説明していました。

この設定だと20%のDataは学習した結果が正しいかどうかを確認するためだけに使用されるそうです。

そしてOverfitting(たぶん過学習の事)について解説しています。

次の実装です。

お、Learnerが出て来ました。

ここで使用しているResnet34の34は34のLayerを作成する事を示しているそうです。

MetricはPredictionの正確性を示すためのParameterだそうです。

後、隠れParameterとしてPretrainというのがあるそうです。

既に前に学習した内容を使用する事が出来るParameterだそうです。

これって一番おいしい所じゃね。

と思ったら少なくともこの教科書が書かれた時点ではこの分野はほとんど研究されてないそうです。

うーん。残念。

多分、今は違うと思いますが、この教科書でその分野について勉強する事は出来ないって事ははっきりしました。

ただこの分野をTransfer learningという事は分かりました。

次のCodeです。

お、やっとFine Tuneについての説明が来ました。

Parameterを結果からUpdateする工程を指しているみたいです。

先週のBlogには以下のように書いていました。

うーん。

どっちが正しいのか。

Copilot先生に聞いてみます。

これ見ると、今回勉強した教科書の説明があっているようです。

<What Our Image Recognizer Learned>

もう時間が無くなってしまいました。

ここからは来週勉強する事にします。

3.1.2 Jupyterについての調査

これは来週やります。

3.2 Nvidia Omniverseの勉強

これがしたかった。

私の専門は3D Graphicsです。

仮想空間で生成AIを使用したRobotのTrainingを勉強すれば他の生成AIの専門家に差をつける事が出来るはずです。

これについて調べたらNvidiaのOmniverseにNVIDIA Isaac SimというPluginを入れてTrainingしているらしい事が判明しました。

今回はNvidiaのOmniverseのTutorialについて調べます。

YouTubeにあるTutorialだけ調べます。

Nvidia Omniverseと言うChannelがありますね。

更にNvidia StudioのGetting Started in NVIDIA OmniverseというTutorial Seriesがありました。

NVIDIA omniverseにある動画を見てみました。

こっちはOmniverseの最新の機能の紹介が主みたいです。

最新の動画が4カ月前のものですね。

次にGetting Started in NVIDIA Omniverseを見てみます。

こっちもNvidia Studioが制作した動画でした。

その中で初心者向けのモノをひとまとめにしたみたいです。

最初の何本かのTutorialを軽くですが、見ました。

基本的な操作はUE5とほぼ同じです。

UIが違うのと、ProgrammingにPythonを使用するのが違います。

これだけ見た感じではOmniverse単体の仕様方法を覚えるのはそんなに難しくなさそうですね。

次にNvidia Omniverseを使用した仮想空間におけるRobotのTraining方法(NVIDIA Isaac Sim)について調査します。

こっちもYouTube先生に聞く事にしました。

これもNvidia StudioのTutorialがありました。

更に下を見たら

sentdex氏のTutorialがありました。

その次に表示されていた

Skyentific氏のFrom Reality to Simulation with Isaac Sim (+ RTX3080Ti raffle) [9]は軽く全部見たんですが、非常に分かり易かったです。

ただしこのTutorialではRTX3080Tiを使用してSimulationしていました。

Simulationに必要なPCの要求はかなり高そうです。

その次のTutorialもかなり興味深いですね。

これぐらい簡単なModelで大体の全体像を理解したいですね。

4. Materialの勉強

今週はMaterialの勉強をする時間は取れませんでした。

これらは来週やる事にします。

4.1 Pwnisher氏のTutorialの勉強

4.2 Ben Cloward先生のTutorialの勉強

4.3 Substance Designerの勉強について

 5. Gaeaの勉強

5.1 Buildについて今まで勉強した内容をまとめる

兎に角Blogを徹底的に調査してBuildについて述べている箇所をここにまとめます。

2023-11-19のBlog

TerrainのSizeの設定方法について説明しています。

更にPixelに対してのSizeについての解説もここで説明しています。

この辺の内容は忘れていました。

2023-08-06のBlog

ここでは今までのBuildの勉強をまとめていました。

の内容がまとめられていました。

ここでは実際に作成したTerrainの高さを調べる方法や、Height MapはPng、それ以外のMaskはpng8でExportするとかが書かれていました。

それ以外の設定については以下のようになっていました。

それぞれのParameterについてもColor Space以外は詳しく解説されていました。

Color Spaceに関しては公式SiteのBuild Manager [10]に以下の解説がありました。

後、高さを調べる方法でm単位で高さを指定する方法も説明されていました。

全部見なくてももうBuildの設定の大半はこれでまとめられていますね。

後必要なのは、どのNodeをBuildに追加するかです。

5.2 どのNodeをBuildに追加するか

Final Terrainの結果を追加します。

そしてそれぞれのMaskの結果も追加します。

Maskに使用するData GroupのNodeはOutputが複数あるNodeもあります。

その場合は全部のOutputの結果が出力されてしまいます。

それを防ぐには上記の様にFxノードを追加してそれを出力するか、以下のBuildの設定を変更する必要があります。

Maskに使用しているNodeは全部Gray ScaleなのでFxノードを使用すれば良いです。

5.3 Klaus氏のTutorialでExportするNodeの指定方法を確認する

一応、Klaus氏のTutorialで確認します。

How To BUILD AN ISLAND In 20 mins | Unreal Engine 5 Tutorial [11]で確認しました。

あっています。

PngとPng8の違いは

Copilot先生によると

となっています。

Height MapとMaskは両方、Gray ScaleなのでPngとPng8における違いは無い気がします。

5.4 Tutorialの作成する順番

BuildのTutorialの作成する順番についてまとめます。

  • SizeとHeightの設定について解説します。
  • HeightmapとMaskの指定方法について
  • とそれ以外のBuildのParameterについての解説とBuild

の3本で行う事にします。

6. UE5.4の新しい機能について

6.1 Unreal Engine 5.4 Plant Growth Effect Tutorial In Under 5 Mins [4]を実装する

今週は時間が無いので簡単なこっちのTutorialを実装する事にします。

まずLevelの作成を行います。

先週のBlogを見るとLevelの作成方法については何の説明も無いと書かれていました。

いつもの設定を追加して空を作成しました。

Mega Scanを利用して使用するAssetを追加します。

以下の3つのAssetを追加しました。

Tutorialと同じ名前のAssetが何個もあったのでその中から近そうなのを選びました。

まずStatueを配置します。

これらのAssetから以下のPlantをLevel上に追加しました。

以下のように原点に配置しました。

Scaleは0.2にしました。

Motion Designに入りました。

Actorを選択して、更にClone Actorを選択します。

ClonerにCubeを消して以下のAssetを追加しました。

CloneのParameterの設定を変更します。

Layout NameをMeshに変更しました。

Sample ActorにStatueをセットしました。

結果です。

あれ?

草がStatueから離れた位置に生成されていますね。

ひょっとするとこの後の調整でこの問題も解決するかもしれません。

続きをやってみます。

LocationのZの値を0.01に変更しました。

結果です。

む。

先週のBlogに書いた通りGrassの色が劇的に変化しました。

今度はEffectorを追加します。

Effector Rotationと名前を変更しました。

Typeの値をUnboundに変更しました。

Rotationの値を以下のように変更しました。

Clonerに戻り、ClonerのEffectsにこのEffect Rotationsを追加しました。

結果です。

やっぱり隙間があいています。

Grassの向きを以下のように変更しました。

結果です。

Statueより離れた位置から草がはえていますが、それなりにそろって生えるようになりました。

Countの値を4000に変更しました。

結果です。

うん。

これなら良いでしょう。

新たなEffectorを追加します。

間違えて以下のPanelを閉じてしまいました。

このPanelの名前が分かりません。

色々調べたらどうやってこのPanelを表示するのかが分からないです。

Copilotに質問しました。

全然、検討違いの回答をしています。

分かりました。

以下の赤の部分の設定をMotion Design Modeにする必要がありました。

すると先程のPanelが表示されます。

Effectorを追加しました。

名前はEffector Animationに変更しました。

更にTypeをPlaneに変更しました。

更にEasingの値をIn Out Cubicに変更しました。

Scaleを0にしました。

CloneにこのEffectorを追加しました。

PCが動かなくなりました。

再起動しました。

分かりました。

EffectorAnimationには2つのLocationがあります。

それぞれのScaleの値が違っていました。

まず以下のScaleの設定は0です。

こっちはXYZがあります。

次に以下のScaleの値は0.1にセットしていました。

またUEが動かなくなりました。

Countの数が4000なのが多すぎるんですよ。

1000位に下げます。

遂に以下のようになりました。

Effector Animationの向きを以下のように変更しました。

Effector AnimationをSequencerに追加しました。

位置を指定しました。

これで草が生えるようになりました。
Tutorialはここで終わっていますがCameraを追加してRenderingして映像としてまとめます。

youtu.be

Davinci ResolveにImportしたら12秒の動画になっていました。

この辺の編集方法は勉強したんですが、理解したやり方で直そうとしたら直らなかったです。

今回はSpeedを編集する事で直しました。

6.2 Unreal Engine 5.4 Plant Growth Effect Tutorial In Under 5 Mins [4]を実装した感想

まさかEffectorにLocationを示すParameterが2つあるなんて想像もしなかったです。

後、私のPCのSpecではCloneのCountの値が4000では処理しきれなかったです。

RTX3070Tiなのでそんなに悪いとは思ってないですが、やっぱりVRAMが少ないからなんでしょうか。

予想していた時間の3倍位消費してやっと完成しました。

でも出来た時はかなり感動しました。

6.3 公式のSequencer Editor [5]を勉強する

これ見てください。

先週勉強したCameraのIconがありません。

何でなんでしょう。

まだSequencerには分からない事が沢山あります。

<Outliner>

以下の部分の事です。

ここには特に情報な情報は書かれていませんでした。

もしOutlinerのもっと細かい情報を勉強したい時は別なPageで解説しているそうです。

<Timeline>

以下の部分はTimelineと呼ぶそうです。

ここで赤い線をEnd Marker、緑の線をStart Markerそして白い線をPlayheadと呼ぶ事を知りました。

<<Navigation>>

このTimelineの操作の仕方を説明しています。

と言っても右端と下にあるBarの操作方法の説明だけです。

右端のBarは単に移動させるだけですが、下のBarはPanとZoomの機能があります。

下のBarの真ん中の濃い灰色の部分にCursorを抑えて移動すると、PanになりTimelineはHorizontallyに移動します。

両端の薄い灰色の部分をCursorを合わせて移動すると、Barの長さが変化してTimelineがZoomします。

更にMouseの右Clickをした状態でTimeline上を移動すると上下左右に移動する事が出来るそうです。

6.4 Sequencer EditorCine Camera Actor [6]を勉強する

今週はLens Settingについて勉強します。

これ。

今回はFStopについて勉強します。

Apertureって何の事でしょう?

それ以前にFStopってCameraの世界では普通に使用している言葉なんでしょうか?

WikipediaのApertureに以下の説明がありました。

By KoeppiK - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=78136658

Cameraには上記のような絞りの機能がついています。

この絞りの大きさを指定するのがApertureでした。

ただWikipediaの説明は専門的すぎてよく分かりません。

CopilotにApertureについて質問しました。

Exposureの値が変わるのは理解出来ます。

そもそもLensに入って来る光の量が変化しますから。

次のDepth of Fieldの値が変化するのはかなり複雑な内容です。

Apertureの値を大きくした場合(F-Numberの値は小さくなるそうです。)背景がBlurになるそうです。

えー。

そうなの。

以下のCameraで試してみます。

Max FStopの値を10まで下げてみました。

結果です。

うーん。

なんの変化も無いですね。

Gaussian Splattingは元々背景がぼやけているからかもしれません。

以下のLevelでもう一回試してみます。

Max FStopの値を10に下げました。

結果です。

うーん。

変わってないですね。

この値は無視して良い気がします。

7. Houdiniの勉強

7.1 Houdini 19 - Wall Tool 13 [12]を実装する

<Intro>

Type Propertiesを開き以下のようにExisting ParametersにFolderを追加しました。

名前はMaterialsとしました。

そしてそのMaterialの下にBrick Face、Brick ChipそしてGroutの3つのFolderを追加しました。

MaterialsのFolder Typeの値をSimpleに変更しました。

更にFileのImageをBrick Faceに追加しました。

以下のようになりました。

名前とLabelの値を以下のように変更しました。

さらにDuplicateして4つに増やしそれぞれの名前を以下のように変更しました。

Brick Chipも同じようにしました。

Groutにも同様のFileを作成しました。

次にEditorに戻り、Material Networkノードを追加しました。

先週のBlogでまとめた時と同じように名称がMatnet1になりました。

Matnet1ノードをDouble ClickしてそのNodeの中に入り込みました。

Principle Shaderを追加しました。

先週のBlogには

とまとめてあったので、

試してみました。

以下のIconを押したら

以下のWindowが開きました。

はい。

ここから説明を読む事が出来ます。

次は以下の機能を解説していました。

これも確認出来ました。

ただ実際にCopperを選択して試すとかまではやりませんでした。

BrickFaceと名前を変更しました。

Alt+Dragでもう2つ同じNodeを作成しました。

名前を以下のように変更しました。

先週のBlogに以下のように書いていました。

これもう一回Tutorial見てみますか。

<<Use Point Color>>

多分だけと分かりました。

OpenGLを勉強した時に以下の疑問があった事を思い出しました。

それぞれのVertexって色の情報を保持する事が出来たんですが、実際の色はShaderで指定していました。

じゃあVertexが色の情報を持っていても意味なくない。と思ったんですが、その疑問は解決される事はなかったです。

その代りOpenGLの内容なんかほとんど忘れてしまった今でもその疑問を持ったことは覚えていました。

ここで言うPoint ColorとはそのVertex一つ一つが持つ色の情報の事のようです。

その情報も使用するというのがこのParameterの機能みたいです。

<Linking Parameters>8:30

ここから作成したNodeとType Propertiesを繋げるための設定を行うそうです。

Brick Faceノードを選択します。

Textures Tabを選択します。

Base ColorのUse TextureにCheckを入れます。

Type Propertiesを開いて、MaterialsのBrick FaceからDiffuseを選択します。

Tabから以下に示したChannelsを選択します。

以下に示したVEX BuilderのBrick FaceノードのParameterであるTextureをDrag して

Type Propertiesの以下の箇所にDropします。

しました。

結果です。

Tutorialと同じ結果になりました。

Type PropertiesのApplyを押してしばらく待つと、VEX BuilderのBrick FaceノードのParameterのTextureの部分が以下のように変化しました。

Tutorialでは以下のように変化しています。

色は変化しましたが、Codeは表示されませんね。

うーん。

分からん。

このまま先に進みます。

Ambient OcclusionとRoughnessも同様に行います。

次にNormalの設定を行います。

Nodeの方のBrick FaceのPropertiesのTabをBump & Normalに変更します。

以下のParameterを使用しました。

まずEnableをCheckします。

そしてTexture PathをType PropertiesのNormalの

Drop Parameters here to add new linksにDropします

するとLinked ChannelsにそのPathが表示されます。

更に以下のApplyを押して

数秒待つと

BrickFaceノードの方のPropertiesのTexture Pathの色が緑色に変化しました。

<Adding Textures>10:45

ここで使用するTextureをTextures.comから取得します。

このSiteは使用した事はありません。

兎に角やってみましょう。

一端、Houdiniを閉じます。

Textures.comを開きました。

Freeのところを見たんですが結構凄いです。

試しにDownloadしてみます。

これをDownloadしてみますか。

あれ?

なんかCreditが必要とか出てます。

調べます。

RedditTextures.com no longer free? [13]に以下の質問がありました。

これ5カ月前の掲載ですね。

という事は半年前にTextures.comはその方針を変更したみたいですね。

Poly Havenと言うSiteがFreeでTextureをDownload出来るそうです。

そっちを見てみます。

このSiteです。

Havenは避難所で、Heavenが天国です。

そしてHavenの読み方はヘエイヴンでHeavenの読み方はヘヴンです。

以下のTextureをDownloadしてみました。

別に登録しなくてもDownload出来ました。

開くと以下のようになっていました。

NormalとRoughはexrというExtensionですね。

調べます。

うーん。HoudiniはExrは普通に使用出来るみたいです。

Ambient Occlusionが無い代わりにDisplacementがあります。

うーん。DisplacementをAmbient Occlusionとして使用しますか。

このTextureはBrick Faceに使用します。

Brick Chip用のTextureもこれで良いです。

Grout用のTextureを探します。

これをDownloadしました。

こっちも同様です。

Textureを取得したのでHoudiniに戻ります。

今、この階層にいますが、

Uを押すと一つ上の階層に移動出来るそうです。

試してみます。

一つ上の階層に移動しました。

これは便利です。

更にもう一回Uを押してもう一つ上の階層であるBrickwall_tool_buildに移動しました。

Brickwall_tool_buildのPropertyを見ると

以下に示した様に

Materialsの項目が追加されています。

ここに先程DownloadしたTextureを追加します。

以下のようにセットしました。

あれ?

VEX BuilderのBrick ChipとGroutの設定はやって無いですね。

まあ先に進みます。

後で、既にやった事になっていたらその時にやる事にします。

以下のTextureをEnableします。

結果です。

何も変化していません。

これはTutorial通りです。

まず以下の場所にMaterialノードを追加しました。

Propertiesを見ます。

あHoudiniだからParameterか。

以下の赤で囲ったTabを3つに増やします。

上のNumber of Materialsの値に3を入れたら3つに増えました。

それぞれのGroupにBrickFace、BrickChipsそしてGroutを追加しました。

次にMaterialをセットします。

以下のBoxを開いて

BrickFaceを追加しました。

結果です。

おお凄い変化している。

でもこのTextureはBrickには見えませんね。

この後、Brick ChipとGroutにも同様の作業を行うそうですが、VEX BuilderのBrick ChipとGroutの設定はやって無いので何も表示されないはずです。

VEX BuilderのBrick ChipとGroutの設定を今やります。

まずはLinking Parameterを行います。

ここはやっている事は同じなので最後の結果だけ記録しておきます。

Brick ChipのNormalのTexture Pathです。

GroutのNormalのTexture Pathです。

今度はBrickWallTool_BuildノードのParameterの設定を行います。

それぞれ以下のようにSetしました。

結果です。

あれ?

Textureが適応されていません。

これはなんかの作業を忘れていますね。

今週はここで時間が無くなってしまったので、VEX BuilderのBrick ChipとGroutの設定の確認は来週やる事にします。

調べるまでも無かったです。

Material1ノードの以下の部分の設定を忘れていただけでした。

結果です。

うーん。

これは後から沢山直す必要があります。

どう見てもBrickとGroutではないです・

後、Specular Lightが金属のそれです。Roughnessの値をもっと高くしてSpecular Lightを下げる必要があります。

<Adding Global Scales>15:00

後、この節だけなのでやってしまう事にしました。

TextureのSizeを変更するための機能を追加します。

Type Propertyを開いてFloatをMaterialに追加しました。

名前とLabelを以下のように変更しました。

RangeのMinの値に0.1をセットしました。

VEXの階層に移動して

BrickFaceノードを選択して

Scaleを

先程のType PropertiesのUV Scaleの

以下のChannelにセットします。

以下のようになりました。

で、ここからが問題です。

同様に残り2つのNodeのScaleもType Propertyのこの値とBindさせる必要がありますが、

Tutorialは色々な方法で試したんですが、出来なくて最後は以下のCommandを追加していました。

これは最終手段として別な方法を試してみます。

無理やり3つとも追加してみました。

BrickFaceノードの結果は以下のようになっていますが、

BrickChipノードとGroutノードの結果は以下のようになりました。

うーん。

PathのAddressがTutorialと違う。

これで出来るのかTestしてみます。

テストしようとBrickwall_tool_buildの階層に戻ってきたら

以下のように既に変化していました。

TextureのSizeが10分の1に変化していました。

Brickらしくなってきました。

出来てますね。

ここでTutorialは終わっているので今週のHoudiniの勉強はここまでとします。

8. UEFNの勉強

今週からPi equals Three氏のTutorialは以下のUEFN Tutorialsではなく

全部やる事にします。

何故からそうしないと話が繋がらないからです。

例えば、今週勉強する予定だった以下のTutorialですが

Part2となっていてPart1を既に勉強した前提で話が進んでいます。

しかしこのTutorialのPart1と思われる以下のTutorialはUEFNのPlaylistには入っていません。

本当に勉強しにくい。

こんな感じで並んでいます。

緑が先週まで勉強していたTutorialで、赤がPlaylistの次のTutorial、オレンジが赤で囲ったTutorialのPart1と思われる動画です。

するとその間にExtension Functions? Fortnite UEFN/Creative 2.0 Verse Tutorial [14]があります。

今週はこれを勉強します。

8.1 Extension Functions? Fortnite UEFN/Creative 2.0 Verse Tutorial [14]を勉強する

ここでは以下のようにそのClassが本来持っていないFunctionを追加する方法を勉強します。

うん。

これって結構重要な内容じゃない。

こうやって本来はそのClassに存在しない後から追加したFunctionの事を

と呼ぶらしいです。

ここでらしいというのは

Documentで確認したら見つからなかったと言っています。

まあ、それはどうでも良い事です。

実際のやり方を勉強しましょう。

まず普通にFunctionとして作成する場合です。

PlayerをParameterとしてPassしています。

で、Extension Functionとしてこの関数を作成すると以下のようになります。

最初にExtensionするClassとそのObjectの名前を指定します。

その後に関数名、で後は普通の関数の作成と同じになります。

関数名の前にDotがありました。

Cursorで見えなかったです。

以上でした。

う、短い。

でもまあいいでしょう。

今週のUEFNの勉強はこれで終わりです。

9. DirectX12の勉強

9.1 Lötwig Fusel氏のD3D12 Beginners Tutorial [D3D12Ez]を勉強する

9.1.1 Creating a Window | D3D12 Beginners Tutorial [D3D12Ez] [15]の次の10分を実装する

<Shutdown Method>

DXWindow ClassのInit()関数の最後にReturnを追加しました。

Shutdown()関数にUnregisterClassW()関数を追加してw_wndClassを開放します。

<Creating the window>

Main.cpp fileに戻って作成したDXwindow ClassのInit()関数が動くか確認します。

まずWindow.h FileをIncludeします。

DXwindow ClassのInit()関数を実装しました。

これでこのProjectを実行したらDXwindow ClassのInit()関数は呼び出されるはずです。

WhileにBreak Pointを追加してTestしてみます。

結果です。

ErrorにならずWhile LoopのBreak Pointのところまで実行されています。

という事はDXwindow ClassのInit()関数は普通に呼び出されて実行されたという事です。

出来てます。

Window.cppに戻ります。

Init()関数の最後に以下の実装を追加しました。

これで実際のWindowを作成しています。

<Creating the window handle>

Windows Handle型の変数を作成します。

こっちはNullptrを使用していますね。

何でATOM型の変数を宣言した時は0を使用したんでしょうか?

Copilot先生にNullptrと0の違いを聞いてみました。

出来るだけNullptrを使用しろって言っています。

ATOM型は形無しともいえるので0しか使用出来ないのかもしれません。

Copilot先生に聞いてみました。

成程、Classを後から指定するがその指定に失敗した時は0を返すから最初は0にしておいたほうがいい。

からか。

後の理由はよく分かりませんね。

作成したHWND型のVariableであるm_windowで先程作成したCreateWindowExW()関数のReturn Valueを受け取ります。

更に正常なReturn Valueを受け取れたのかどうかのCheckをするための実装も追加します。

M_windowの値がNullptrでなければTrueを、NullptrであるならFalseを返すはずです。

<Testing the window>

実行します。

巨大なWindowが表示されました。

出来てますね。

今度はこのWindowと対話できるようにしていきます。

Window.h FileのDXwindow ClassにUpdate()関数の宣言を追加します。

更にWindow.cpp fileにこの関数の実装を追加します。

ここで先週の勉強は終わっていました。

ので今週の実装はここまでとします。

9.2 DirectX 12の魔導書」の勉強

9.2.1「4.11 三角形ポリゴンを四角形にしてみる」の「4.11.2 Indexを利用する」を実装する

PrimitiveのTopologyの設定がD3D_PRIMITIVE_TOPOLOGY_TRIANGLELISTのままで四角形を作成する方法を勉強します。

<Indexを使う理由>

簡単にまとめると、Indexを使用した方が呼び出しCostが減るからです。

<Indexの実装方法>

ここが難しそうな所です。

3つのIndexで1つ、という事と時計周りに指定する。の2つの規則があるそうです。

これをIndexのDataとしてGPUに送ります。

まずBufferを作成します。

BufferはCreateCommittedResource()関数を使用して作成します。

CreateCommittedResource()関数はVertexのBufferを作成する時も使用したそうです。

うーん。

そうなのか。

憶えていません。

Sample CodeでCreateCommittedResource()関数を探してみました。

うーん。

確かに使用しています。

しかい全く覚えていませんね。Blogから調べてみます。

2023-12-03のBlogにまとめられていました。

まずCommittedのSpellを間違えて書いていた。と書かれています。

ああ。

思い出した。

この関数か。

この関数のParameterとして使用する2つのStructについて以下のように説明していました。

Index用のCreateCommittedResource()関数見直すと、確かにここで説明されている2つのStructを使用していました。

Heappropは以下のように指定されていました。

Resdescの設定です。

教科書の内容に戻りますが、この後の説明がかなり複雑です。

まずその内容を以下に簡単にまとめます。

以下の4つの作業を行っています。

  1. Mapを利用してBufferにDataをCopy
  2. Index用のBuffer Viewを作成
  3. Index Bufferのセット命令を設定(描画時)
  4. DrawInstanced()関数をDrawIndexedInstanced()関数に交換する

それぞれについて簡単に解説します。

<<Mapを利用してBufferにDataをCopy>>

そもそもCreateCommittedResource()関数のVertBuffがBufferじゃないの?

と思ったらVertBuffは

ID3D12Resourceという型で、BufferとしてGPUには遅れないみたいです。

うん。

何でVertBuffって名前になってるの。

あ。

VertexをBufferとしてGPUに送る方の実装をみてた。

IndexをBufferとして送る方の実装は以下のようになっていました。

ResdescのWidth以外の値はそのままで、HeappropとResdescはVertexのBufferを作成した時のモノを使用していました。

ID3D12Resource型の変数の名前はIdxBuffとなっていました。

ではMapを使用してBufferにDataをCopyします。

うーん。

薄っすらとこれを勉強した記憶はありますが、何を勉強したのかはまるで覚えていません。

2023-12-10のBlogを見たら、VertexのMapを使用したCopyについてしっかりした解説がまとめられていました。

しかもこの時のBlogを読むと、先程のCreateCommittedResource()関数は、GPU側にこれからBufferとして送るDataが保存できるように、Memoryを確保する。と説明していました。

でMap()関数がその領域にBufferのDataを書き込むそうです。

しかしもっと正確に言うと

だそうです。

ああ、理解しました。

こういう事だと思います。

まずGPU側のBufferのDataを保持するためのMemoryのAddressを保持するための変数を作成します。

Map()関数を利用してそのGPUのAddressをこの変数に保持させます。

Copy()関数を利用してそのGPU側のAddressにBufferの情報をCopyします。

最後にMapを解放します。

うーん。

でもこの解釈だと最後にUnmap()関数を呼び出す必要ってあんまり感じないですね。

だってMappedIndexがGPU側のこのBufferのAddressをずっと保持していたって別に問題ないですよね。

うーん。

これは思っていたより問題は複雑そうです。

教科書の「4.4.1 ID3D12Resource::Map()Method」を読み直します。

大体はこの説明であっている気がしますね。

とりあえずはこれで良しとします。

<<Index用のBuffer Viewを作成>>

以下の方法で作成していました。

これもVertexの時の勉強を確認します。

2023-12-10のBlogでは以下の事しか書いてなかったです。

「4.4.2 Vertex Buffer Viewの作成」も読み直してみます。

分かりました。

これは単にBuffer Viewの設定を指定しているだけでした。

<<Index Bufferのセット命令を設定(描画時)>>

Buffer Viewは作成しただけではGPU側に伝わらないので

描画時にIASetIndexBuffer()関数を使用してIndex Bufferをセットします。

これもVertexの時にどんな勉強したのかを調べます。

2024-05-12のBlogで勉強していました。

何と、教科書の「4.10.3 描画命令」でこれを勉強していました。

とんでもなく後になってBuffer Viewの情報をGPU側に送ったのか。

「4.10.3 描画命令」を勉強した時は、これがVertex Viewの情報をGPU側に送っているなんて認識は全くなかったです。

2024-05-12のBlogでは特に重要な内容は書かれていませんね。

一つだけ面白かったのは以下に示した

Sample CodeにはIASetIndexBuffer関数が書かれているが、教科書にはこのCodeの説明がまったく書かれてない。というくだりです。

<<DrawInstanced()関数をDrawIndexedInstanced()関数に交換する>>

Sample Codeには以下のように2つとも書かれていました。

Indexの数は6個なので6が指定されています。

一応、公式のID3D12GraphicsCommandList::DrawIndexedInstanced method (d3d12.h) [16]を読みます。

Syntaxです。

それぞれのParameterについても簡単にまとめます。

これはIndexの数を指定するだけですね。

Instanceの数を指定するそうです。

どのInstanceを指しているのか今一分かりませんが、一個しか存在しないと思いますので、ここは常に1になると思われます。

これは0以外から始まる場合もあるんでしょうか?

これも0以外を指定しないといけない場合が思いつきません。

これに関しては何故、こんな値を指定する必要があるのかすら分かりません。

0でいいでしょう。

以上でした。

なんと、ここで4章は終わっていました。

車を適当に走らせていたら突然海岸に出た感じです。

来週実装して、4章のまとめ、並びに4章を勉強した感想を書く事にします。

10. まとめと感想

特になし。

11. 参照(Reference)

[1] Jeremy Howard. (2022, July 21). Practical Deep Learning for Coders: Lesson 1 [Video]. YouTube. https://www.youtube.com/watch?v=8SF_h3xF3cE

[2] pwnisher. (2024, May 11). Unreal engine materials in 6 levels of complexity [Video]. YouTube. https://www.youtube.com/watch?v=iZgbzwBQTPY

[3] WINBUSH. (2024, April 24). Official Android support for Unreal Engine virtual camera [Video]. YouTube. https://www.youtube.com/watch?v=bzFM0HdLYSU

[4] Unreal Katya Fedak. (2024, April 10). Unreal Engine 5.4 Plant Growth Effect tutorial in under 5 mins [Video]. YouTube. https://www.youtube.com/watch?v=JJyJD_QDLy0

[5] Sequencer Cinematic Editor Unreal Engine | Unreal Engine 5.4 Documentation | Epic Developer Community. (n.d.). Epic Developer Community. https://dev.epicgames.com/documentation/en-us/unreal-engine/sequencer-cinematic-editor-unreal-engine

[6] Cinematic Cameras in Unreal Engine | Unreal Engine 5.4 Documentation | Epic Developer Community. (n.d.). Epic Developer Community. https://dev.epicgames.com/documentation/en-us/unreal-engine/cinematic-cameras-in-unreal-engine?application_version=5.4

[7] Rick Banks. (2022, June 28). Houdini 19 - Wall Tool 13 [Video]. YouTube. https://www.youtube.com/watch?v=NU60wnBsIkM

[8] Lötwig Fusel. (2023, June 5). Creating a Window | D3D12 Beginners Tutorial [D3D12EZ] [Video]. YouTube. https://www.youtube.com/watch?v=yBKQLxkcXz4

[9] Skyentific. (2022, September 19). From Reality to Simulation with Isaac Sim (+ RTX3080Ti raffle) [Video]. YouTube. https://www.youtube.com/watch?v=KDG4d97DdI4

[10] Build Manager - GAEA Documentation - QuadSpinner. (n.d.). QuadSpinner Gaea Documentation. https://docs.quadspinner.com/Guide/Build/Manager.html

[11] Klaus. (2022, May 21). How To BUILD AN ISLAND In 20 mins | Unreal Engine 5 Tutorial [Video]. YouTube. https://www.youtube.com/watch?v=Obfq-Zh3iXs

[12] Rick Banks. (2022, June 28). Houdini 19 - Wall Tool 13 [Video]. YouTube. https://www.youtube.com/watch?v=NU60wnBsIkM

[13] Textures.com no longer free? (n.d.). Reddit.com. https://www.reddit.com/r/gamedev/comments/196fr11/texturescom_no_longer_free/

[14] Pi Equals Three. (2023, June 15). Extension Functions ? Fortnite UEFN / Creative 2.0 verse tutorial [Video]. YouTube. https://www.youtube.com/watch?v=Crenr9EClZw

[15] Lötwig Fusel. (2023, June 5). Creating a Window | D3D12 Beginners Tutorial [D3D12EZ] [Video]. YouTube. https://www.youtube.com/watch?v=yBKQLxkcXz4

[16] Stevewhims. (2024, February 22). ID3D12GraphicsCommandList::DrawIndexedInstanced (d3d12.h) - Win32 apps. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12graphicscommandlist-drawindexedinstanced