UE4の勉強記録

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

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

1. 今週の予定

1.1 今週の予定

今週は以下の内容を勉強します。

<Landscapeの作成>

建築用のLevelの作成の勉強の続きをやります。

Lightの配置を行います。

Niagara の勉強>

Unreal Engine 5で学ぶビジュアルエフェクト実装 基本機能からNiagara、シミュレーションまで」の実装をやります。

先週、動かなかった原因を追究します。

<Materialの勉強>

Ben Cloward先生のTutorialの何かを勉強します。

<Gaeaの勉強>

更にGaeaのTutorialを作成します。

<Houdiniの勉強>

Castle Wall Tool [1]の勉強をやります。

<UEFNの勉強>

Pi Equals Three氏のTutorialをやります。

<DirectX12の勉強>

DirectX 12の魔導書」と「Direct3D 12 ゲームグラフィック実践ガイド」の勉強をやります。

更にLötwig Fusel氏のDirectX12のTutorialをやります。

2. Landscapeの作成

2.1 建物の内部にLightを追加する

使用しているLightをOutlinerから調べます。

以下のように使用していました。

RectLightは一回も使用した事がないです。

設定とかどうなっているんでしょうか?

公式SiteのRectangular Area Lights [2]が解説していました。

うーん。

解説を読む限り普通のLightと同じですね。

後、深さの調整Parameterは無いみたいです。

RectLight2です。

こんな所に配置していました。

一緒にあるLightは

でした。

RectLight3です。

家具の無い空き室の天井です。

天井全体とまでは行かないですがかなり大きめなSizeにして配置していますね。

ここも先程のSM_Point_Lampを使用しています。

RectLight5です。

Bathroomの天井です。

ここは天井全体に配置しています。

取りあえずここまでLightを配置してみます。

こんなRadiusがある事が分かりました。

黄色の四角のSizeを変更する方法が分りません。

もう一度DemoのLightを見てみます。

窓のSizeと黄色の枠が同じになっています。

更に、水色の半径を示すLineは以下のような巨大なSizeになっていました。

これらを調整するParameterがどれなのかよく分からないので、

以下にRectLightの全てのParameterを記録しておきます。

まずはこのParameterのDataを元にLightの形状を調整してみます。

自分で作成している建物のLevelに戻って来ました。

RectLightのParameterを比較します。

まずLightのIntensityですが、Demoの方は1.0cdになっていました。

直しました。

次にSource WidthとSource Heightが以下の値になっていました。

直しました。

おお、黄色の枠の形状が変化しました。

黄色の枠のSizeはここで調整していました。

最後の水色の線です。

これはおそらく

で調整しているんでしょう。

試します。

値を500にしました。

球の大きさが半分になりました。

あってますね。

他のParameterでDefault値から変更しているものを調べます。

無いみたいです。

以下の3つのParameterだけ調整出来たら

一応それで良いみたいです。

RectLight2です。

横から見た状態です。

Demoを見直したらこのLightはRectLight3でした。

SM_Point_Lampも配置しました。

何で私が配置したSM_PointLampは灰色がかった色しているんでしょうか?

DemoのLampは以下のように光っています。

以下のMaterialが使用されていました。

私のProjectのSM_PointLampのMaterialの設定です。

Element1のMaterialが違います。

これを直します。

前よりはましになりましたが、DemoのLampと比較するとProの絵画と子供の落書き位の差があります。

Lightの位置を少しだけ下にずらしてみました。

SM_PointLampの淡い光も観察する事が出来るようになりました。

Lightが光っている感じが出ています。

でもまだ変な感じがします。

DemoではPost Effectとかは使用してないのか確認します。

BoxReflectionCaptureが使用されていました。

BoxReflectionCaptureの機能はよく知りません。

調べます。

公式SiteのReflection Capture [3]を読みます。

うーん。

よく分からん。

取りあえず使ってみます。

黄色の線でBoxを示してるのとScreenshotで示してるPanelがあります。

BoxのSizeはこの部屋と同じにしました。

このPanelは何を表しているのかまだ不明です。

UE4 Reflection Captures - How-to Use [4]を見たらUE4の場合ですが、非常に分かり易く説明していました。

簡単に言うとReflectionある物体を配置した時でRay Tracingを使用してない時に使う必要があります。

となると今回のLampが本物っぽくないのとは関係ないですね。

他の部屋には反射する装飾品や窓などがありますので、その時にReflection Captureの機能を勉強する事にします。

その時は表面的な使用方法だけじゃなくてReflectionの何を計算するのに使用されているのかとかの理論もしっかり勉強する事にします。

DemoのLampを見るとBloomとかの設定もいじってそうです。

これは Unreal Engine 5 for Architecture - 2023 Full Beginner Course [5]の勉強に戻った時に検討する事にします。

残りの部屋のLightやLampも配置します。

急用を思い出しました。

今週のBuildingの作成はここまでとします。

3.Niagara の勉強

先週は、Game of Lifeの実装を終えたんですが、動きませんでした。

今週はそのBugを直します。

3.1 Bugの原因の推測

まずBugの原因として考えられるのが2つあります。

一つ目は以下に示した警告の原因が分からない事です。

これ自体は警告なのでBugの直接の原因ではないでしょうが、この原因の意味が分からないんです。

のでこれとBugが関係しているのではと疑っています。

2つ目のBugの原因と考えられるのが

これです。

この[StackContext]Stateを2回作る必要があったのは、どこかを間違えて作成した可能性があります。

とは言えこの2つはどこを直したら直るのか分からないです。

ので別な角度からBugを直す方法を考える事にします。

3.2 どうやってBugの原因を追究するか?

Bug出しをするのに全体の構成を理解しておくのは重要です。ので一回Blogを読み直すのはどうでしょうか?

後は、Debugしてどこまでは出来ているのか確認するのも手です。

そう言えばNiagaraでDebugってした事無かったです。

調べたらNiagara Debugger [6]と言うのがあるそうです。

これを読んでいる内にある事に気が付きました。

私が先週作成したGame of LifeNiagara System画面のParameterのStack Context Sensitiveを見ると

[StackContext]Stateはありません。

以下のTexture to Grid 2D Once SectionにあるTexture to Grid 2Dを開いて

以下のようなScratch Module画面になった時だけ[StackContext]Stateは現れます。

それに対してSample CodeではNiagara Systemの画面のParameterの時点で

[StackContext]Stateは表示されています。

これは最初に[StackContext]Stateを作成した時に作成方法を間違えたんです。

Textbookを見て確認します。

Textbookを見直すと、Scratch Pad WindowのParameterから[StackContext]Stateを作成する。と書かれていました。

これが間違っているはずです。

これはScratch Pad WindowのParameterからではなくNiagara SystemのParameterから追加する必要があるはずです。

これを試してみます。

Niagara SystemのParameterから[StackContext]Stateを作成しました。

Scratch Pad Module内に2つの[StackContext]Stateが作成されているかと思ったんですが、それは無かったです。

結果ですが、

何も表示されません。

それぞれのModule内における[StackContext]Stateの値がどうなっているのかを確認したいですね。

さっきのDebuggerだ。

これを使ったら[StackContext]Stateの値が確認出来るはずです。

出来なかったです。

思い出してきました。

Slove SectionにあるSolve Module内の

Custom HLSL Module内の

以下のCodeが

Stateの値を得る事が出来ないのでは?と疑問に思っていたんでした。

うーん。

でもこれも中身が確認出来ないと分からないですね。

あ、良い事思いつきました。

Sample CodeのGame of LifeをこのProjectにMigrateして動くのか確認してみます。

もしかしたらUE5.3では動かないのかもしれません。

普通に動いています。

うーん。

なんと、こうやって同じProject内でSample CodeのLife of Gameと私が作成したGame of Lifeを見比べると結構簡単に違いが判る事が判明しました。

色々見比べてみます。

はい。

まず一個違いが見つかりました。

Emitter Spawn SectionにあるSet Grid 2DCells Moduleの位置が違っていました。

Sample Codeのは下から2番目にセットされています。

更にSample CodeではSet Grid 2DCells ModuleのGrid2DCollectionにセットされているParameterは

以下に示した様に[EMITTER]Grid2DCollectionがセットされていますが、

私のは

がセットされています。

うーん。

一寸この部分をどうやって実装したのか確認します。

2023-11-12のBlogにこの部分の実装をどうやったのかが載っていました。

最初からこのように実装していました。

教科書でこの部分を確認します。

武者 拓也. Unreal Engine 5で学ぶビジュアルエフェクト実装 基本機能からNiagara、シミュレーションまで (pp.784-785). 株式会社翔泳社. Kindle 版.

と書いてありました。

これは読み飛ばしていました。

直します。

結果です。

まだ何も変化ないです。

他にも間違えている所があるという事でしょう。

更にSample Codeと私のCodeを比較していったらまた間違いを見つけました。

今度はSlove SectionにあるGrid2D_To_RenderTarget Module内の実装で

Make Linear ColorノードのAの値が0になっていました。

本当の値は当然1.0でSample Codeも1.0になっていました。

直します。

結果です。

うーん。

まだPreview画面には何も現れません。

まだ何かの間違いがあるはずです。

ありました。

Sample CodeのSprite Renderer ModuleのAlignmentとFacing Modeの設定は

となっていましたが、

私のは

となっています。

これも直します。

直しました。

しかしPreview画面に変化は現れませんでした。

Typoですが以下のSolve SectionのSpellがSloveになっていました。

します。

うーん。

これ以上は違いは見つかりませんね。

これ以上Bugを直すIdeaも出てこないので一端教科書のGame of Lifeの実装の部分を読み直す事にします。

前回、読んで意味の分からなかった以下の部分の灰色でハイライトした部分の意味も今なら分かります。

武者 拓也. Unreal Engine 5で学ぶビジュアルエフェクト実装 基本機能からNiagara、シミュレーションまで (p.793). 株式会社翔泳社. Kindle 版.

Stack Contextを使用する事で、Grid2D Collectionに新しい変数を追加出来る。って意味です。

今回はFloat型のStateという変数を追加しました。

それが以下に示した[EMITTER][GRID 2D COLLECTION] Stateの正体なんです。

ほら、

試しにこのParameterをNiagara Systemにセットして

そのDetailを見てみると

Float型のState変数が存在しています。

うーん。

そう言う事だったのか。

となると2023-11-19のBlogの以下の解釈は間違っていましたね。

Stack ContextはScopeとは何の関係もなかったです。

そもそもStack Context Sensitiveで生成したStateは[Emitter]のScopeとして生成され直しされています。

うーん。

でもまだこの辺は一寸納得出来てないです。

もう少し後で考える事にします。

Solve SectionのSolve Moduleの解説のところで

以下のように書かれていました。

武者 拓也. Unreal Engine 5で学ぶビジュアルエフェクト実装 基本機能からNiagara、シミュレーションまで (p.807). 株式会社翔泳社. Kindle 版.

これか

Attribute Spreadsheetの使い方を調べてDebugするのが次の工程になりますね。

うーん。

来週やる事にします。

今週はここまでとします。

4.Materialの勉強

4.1 Local Volumetric Fog - Advanced Materials - Episode 23 [7]を勉強します

今週はBen Cloward先生のLocal Volumetric Fog - Advanced Materials - Episode 23 [7]を勉強します。

まずLevel上にCubeを配置します。

そしてそのCubeのMaterialにVolume Fogをセットします。

このVolume Fogの実装をみます。

まずResult Nodeの設定です。

Material Domainの設定が以下に示した様にVolumeになっています。

更にBlend ModeがAdditiveになっています。

今度はまたLevel上に戻ります。

Exponential Height FogをLevel上に追加します。

Tutorialによるとこれを追加しないとFogは表示されないそうです。

そしてExponential Height FogのPropertiesにある以下のVolumetric FogをOnにします。

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

Scattering Distributionの値を0.6に変更します。

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

UEはUnityと違ってFall offのParameterがありません。

のでMaterialの実装でこれを追加する必要があるそうです。

以下の実装を作成します。

この実装はLocal Positionにおける座標を示しているそうです。

この実装だけをMaterialのResult Nodeにつなげると

以下のような結果になります。

次にDistanceノードで中心からのそれぞれの距離を求めます。

中心は0.5になるそうです。

その結果に以下の計算をします。

その結果、真ん中がもっとも明るくなり端に近づくほど暗くなります。

更にその結果に5を掛けます。

白さが5倍になるという事はFogの濃さが5倍になるという事になります。

その結果をExtinctionに繋げます。

はい。

これは通常のMaterialにおけるOpacityと同じだそうです。

Opacityの三次元版だそうです。

結果です。

Fogが球状になりました。

今の実装でもFogの形状を変化させることは結構出来るそうです。

例えば以下のMultiplyノードのBの値を2から下げると

Fogの形状はCube状に近づきます。

次は以下の部分の実装の説明をしています。

何とBen Cloward先生、理論的な内容はUnityで説明しているのでここでは実装内容しか説明しないと言っています。

うーん。

とりあえず実装の説明だけ全部聞きます。

その後でUnityの説明を見るかどうかを決める事にします。

Local PositionノードのLocal Positionの値に以下の実装を繋ぎます。

UEの単位はcmなので100で割るそうです。m単位に変更したという事でしょうか?

この値はUV Coordinateの代わりに使用するそうです。

その値とTilingの値を掛けます。

一瞬何をやっているのかと思いますが、UV Coordinateの値を調整していると考えると単にTilingをしているだけだと気が付きます。

そして以下の実装に足します。

Timeノードを使用してTextureが移動するようにしています。

これはぱっと見が難しそうですが、一個ずつ見ていくと結構簡単です。

そしてその結果をTexture SampleノードのUVsに繋ぎます。

このTextureは3DなのにUVsの値はUVだけで良いのかなと思ったら

うーん。

ここは何をしているのか分かりません。

InvLeapノードってどんな計算でしたっけ。

Googleの検索がクソ過ぎて何も引っかかって来ません。

何とか見つけたのが以下の説明です。

この説明があっているのかどうかは不明です。

そうだ。

Bingに聞いてみます。

あれ。

滅茶苦茶しっかり返事が返って来ました。

でもよくSourceを確認したらUnityの内容が混じっていました。

UnityではInverse Lerpは以下の計算を行うそうです。

うーん。

Unrealでも同じでしょう。

これは実装する時に確認します。

Inverse Lerpの話はともかくInvers LerpのTの値は以下のMask(B)の値をPassします。

この値はCoordinateの高さの値だそうです。

おっと。

Tの値につなげる前に1.5倍していました。

先程、以下のように述べましたが

Tutorialでこの部分の実装について解説していました。

この結果をExtinctionにつなげると以下のようになります。

うーん。

Fogの上部の霧を作成していたのか。

Screenshotでは分かりませんが、Fogの上の部分が波打っていて本物の霧のようです。

次に以下の部分の実装を説明しています。

この部分はFogの細かい部分を作成しているそうです。

この部分の計算結果は先程のInverse LerpのBの値に繋がっています。

Multiplyノードの先のNodeについては分かりません。

Wind Directionノードに繋がっていました。

Tutorialではこの実装の細部について簡単に解説していました。

以下のMultiplyノードのBの値は

以下のCoordinateの値がPassされていました。

Texture Sampleノードですがもう一つのTexture Sampleノードと同じTextureが使用されていました。

結果です。

うーん。

確かにFogの形状がもっと細かくなりました。

最後にFogの色の計算だそうです。

SubtractノードのAの値には以下のInverse Lerpの結果が使用されていました。

あれ?

Inverse Lerpが2つあります。

あ、先程のFogのDetailの結果を追加した時に新たなInvert Lerpノードを追加していました。

この実装におけるSmooth StepノードのValueの値をどこから引っ張ってきているのか不明です。

ここから来ていました。

結果です。

うーん。

成程。

多分Unityの説明は聞かなくても大丈夫でしょう。

実装は来週します。

実装していて何か疑問があったらUnityの説明を見るかもしれません。

5.Gaeaの勉強

5.1 今週のTutorial作成は無し

先週、作成したGaeaのTutorialの再生回数が1回でした。

それはまあ良いんですが、Google Analysisを見たらお勧めに表示された回数が1回なんです。

つまり日本中の誰からも私のGaeaのTutorialがある事が知られてない状態になっています。

これは結構応えました。

まあ一応、Tutorial自体は完成させておいてYouTube上に上げておくようにします。

いつどこで誰かが必要にするかもしれませんので。

で、先程のGoogle Analysisなんですが、それを見るとごく少数ですが、第一回のTutorialから見ている人もいるようです。

ただまだ先週のTutorialを見てはいません。

のでそんなに慌てて次のTutorialを上げる必要もないと感じたので今週のGaeaのTutorialの作成はお休みします。

そして今週は別のYouTube用でOpenAI騒動についてまとめる事にします。

5.2 OpenAIの騒動をまとめた感想

Sam AltmanがOpenAIから追放されて奇跡のCome Backを果たしたまでの時系列をまとめました。

動画と同じ話をここに書くのもあれなので、動画を作成するに当たってこれから考えないといけない事についてここで考察します。

それは全然視聴者が付かない事です。

世界で一番再生数を稼ぐMr.Beastが2年は続けないと視聴者は付かないと言っていますが、本当なんでしょうか?

今の視聴者数で2年も続けるのは結構厳しい気がします。

もっと視聴者が興味のある話題の方が良い気がします。

あとYouTubeの特長として勝者が独り占めする傾向が強い気がします。

同じ分野の動画を作成する人が2人いると、優秀な人が全部の視聴者を奪ってしまう感じがします。

残りはGoogleの検索に引っかかるかどうかです。

検索に出てこないものはそもそもNetに存在しないのと同じになります。

そういうSiteも時には重要かもしれませんが、私の動画の場合は望んでないのにGoogleの検索結果に出て来ません。

後は、Click率です。

YouTubeの画面に私の動画が表示された時のClick率なんですが、これはGaeaのTutorialは5%前後あるのに対して、もう一方の動画では0.5~1%前後になっています。

つまり5倍から10倍もClick率が違う事になります。

やっぱりGaeaのThumbnailである以下のアニメ調の可愛い水着の女の子のIllustrationは

Click率が高くなります。

ただその後、ほとんどの人は1分以内に視聴しなくなっています。

つまりClick率だけ高くなっている訳です。

これは単なる感想なんですが、なんか負け組のレールの上を走っている気がしてならないです。

この列車に乗っている限り勝利という駅に到着する事が無い気がします。

どうやってこの電車の載っているレールを変更して勝ち組に乗っかれるのか。

それを考えるのがこれからの課題な気がします。

もうUnrealの勉強は十分しました。

今度はその知識を生かしたどうやって勝ち組のレールに変更するかを検討しないといけません。

これは聞いた話ですが、今GPTsのアプリは1000個出ているそうです。全世界でたった千個です。

このうちの一個をもし自分が作成していたら世界のTop千人の一人として認識されたはずです。

そういう他人から凄いと思われる方法を考えるのかこれから必要な事かもしれません。

6.Houdiniの勉強

一応、先週で Houdini 19 - Wall Tool 02 [8]の勉強は終わったはずです。先週のBlogを見たらHoudini 19 - Wall Tool 03 [9]の勉強も終わっていました。

今週はHoudini 19 - Wall Tool 03 [9]の実装を行います。

6.1 Houdini 19 - Wall Tool 03 [9]を実装する

Houdiniを起動させようとしたら出来ません。

色々なCommentが出て来ますが、よく意味が分かりません。

一回PCを再起動してHoudiniをもう一回起動させます。

うーん。

今度は起動出来ましたが以下のBoxが表示されました。

Karma RenderとかRendererのLicenseって何の事でしょう?

LauncherのLicenseを調べたら以下のように書いてありました。

これを更新する必要があるんでしょうか?

今日の時点では普通に動くので今回は気にしないで実装の続きをやる事にします。

Attributewrangleノードを追加します。

名前はAttributewrangle_fixHalfBrickと言う名前に変更しました。

以下の実装を追加しました。

Codeの内容については先週の勉強で既に調べていますのでここではSkipします。

更に以下のCodeを追加しました。

更に以下の実装を追加しました。

この関数の機能については先週のBlogでしっかり記録してあるので今週はSkipします。

そして以下の実装を追加します。

この関数の機能やそれぞれのParameterについても先週のBlogでしっかり勉強してあるのでここではSkipします。

これでPointが移動するはずです。

あれ?

Errorになってしまいました。

以下の部分がSyntax Errorとなっています。

直しました。

結果です。

Prim Pointの番号は偶数の左端から2番目のPointを見ていきます。

直ってそうですね。

前のPointの位置です。

Attributewrangle_fixHalfBrickを追加した後です。

Geometry Spreadsheetで確認してみます。

おお、Point8の位置がPoint9側によっていますね。

うん。

出来ています。

それではTutorialがやっているようにResample_BrickSpacingノードの

Lengthの値を大きくしてみます。

おお、Pointの幅が大きくなりました。

これもTutorialの通りに出来ました。

今週のHoudiniの勉強はここまでとします。

6.2 HoudiniのVersionをUpdateする

先々週ぐらいにHoudiniのVersionの20.0をInstallしようとしたらErrorになりました。

今週に至っては最初はHoudiniを起動させる事も出来なかったです。

こういう環境の設定で動かなくなるのは凄い自分が怒られている感があって嫌です。

ので今週の残りの時間はHoudiniの新しいVersionのInstallを試して成功させる事にしようします。

今度はあっけなく成功しました。

何で前回失敗したんでしょう。

普通に起動しましたが以下のBoxはVersion19.5と同じように表示されました。

これについては後で調べる事にします。

先程作成したProjectを開いてみます。

以下の警告が表示されました。

Scene Viewの結果です。

何も問題なさそうです。

先程試したのと同じ様に以下のNodeの

Lengthの値を変更したら

以下のように前と全く同じ変化をしました。

はい。

来週からVersion 20.0を使用する事にします。

6.3 Expiring Licensesについて調べます

Houdiniを開くと以下のBoxが表示されるようになりました。

これについて調べます。

調べたけど分かりません。

Which licenses are needed to run which product? [9]にヒントらしきものがありました。

以下のはHoudini FXのCommercial版を使用している場合ですが、RendererとKarma RendererのDefault Qtyには5が当てられています。

それに対してNon-Commercial版のHoudini Apprenticeには1が当てられています。

この5の方のLicenseが後2日で切れますよ。と言っている気がします。

でもよく分からんです。

そもそもCommercial版なんか最初から入っていませんから。

来週になってHoudiniが動かなくなったらもっと真剣に調べる事にします。

Version 20.0の方にもSide FX Labを追加しました。

はい。

以上です。

7.UEFNの勉強

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

7.1 If I Don't Drive Above 40, The Bomb will Go Off! Fortnite UEFN/Creative 2.0 Tutorial [10]を勉強する

今週はこの車を40 miles以下で勉強したら爆発する実装をするそうです。

流石にここまでTutorialを勉強したら大体どんな実装をすべきなのかは想像つきます。

ここにその予測を書いておきます。

まず車用のConstantを作成します。

この型は分かりませんが今は仮にCreative_Prop型と仮定しておきます。

次にあるEventが発生したら車が爆発する関数を作成します。

この関数は車用のConstantにパスします。

そして今度は速度が40Mileを超えたらEventを発生する関数を作成します。

この関数はOn Begin()関数内にセットします。

はい。

これで終わりです。

では実際の実装を見てみましょう。

<Intro>

特になし

<Basic Device Setup / Explosive / Creative prop>

UEFNを開いて車を生成するためにSports Car Spawnerを配置しています。

これは車を生成するためのDeviceだそうです。

こういうのが存在しているという事は知らないですのでこの辺はまだまだ勉強が必要です。

次にExplosive Deviceを配置しました。

こんなDeviceも有るんですね。

はい。

次にProp用のBPを作成して名前をBombPropと名付けました。

ComponentにSphereを追加して

そのSphereのSizeを凄く小さくしました。

これをLevel上に配置します。

そして表示されたSphereとExplosive Deviceの位置を重ねます。

重ねたらBPに戻ってSphereを消します。

うん。

この辺は何が目的でやっているのか今一分かりません。

先に言ったら判明するでしょう。

次をやって行きます。

Detail PanelからExplosive Deviceを選択してBombPropをAttachします。

以下のようになります。

ああ、分かった。

CreativePropでConstantを作成してそれを車に追加するはずです。

ここでVerseに移動します。

以下の名前のVerse fileを作成していました。

<Creating Car Entering Handle Event Method>

以下のConstantを作成しました。

BombはPropに追加すると思ったんですが違いましたね。

更に使用するModuleの設定は以下のようになりました。

OnBeigen()に以下のEvent.Subscribe()関数を追加しました。

Ya Better Start Driving関数をPassしています。

更にYa Better Start Driving関数を作成しました。

<Creating GetSpeed Function to Get Car Speed>

今度は車の速度を得るための関数を作成します。

GetSpeed()関数です。

Return ValueはVoidになっていますが、本当はFloatです。

次に以下の3つの変数を作成します。

あ。ここまで来て分かりました。

Fort_CharacterにはSpeedを表すPropertyは無いんです。

でこれらの変数を使用してSpeedを一々計算するんです。GetSpeed()関数ないで。

以下の実装でSpeedを計算していました。

60mileじゃなくて60km/hでした。

DistanceXY()関数はXYの距離を返すんでしょうか?

最後の計算で3.6をかけているのは3600 sec/hour*1km/1000m = 3.6 (sec*km)/(hour*)mを掛けているからでした。

最後にSpeedKMHの値を返します。

この関数はLoop内で使用されるのはこの時点で明白ですが、この関数内にはLoopはありません。

その場合でも<Suspends>は必要なんでしょうか?
ここはよく分からないです。

<Creating Main Explosion Loop>

ここで車の爆弾がまだ爆発していなのかどうかを検査する関数を作成します。

まず以下の変数を作成します。

Blow Up If Below Speed ()関数を作成しました。

この関数内でLoopを使用するのは明白です。<Suspends>を追加しました。

最初の5秒間Sleepするのは車が加速する間の待ち時間でしょうか?

60 km/hを超えてから爆弾のSwitchが入った方がRealな気もします。

以下の実装を追加します。

これはまあCodeを読んだら何をしているのか明白ですので解説はしません。

<Creating Function to Teleport Bomb to Car>

以下の関数を作成します。

更に以下のConstantを作成します。

うーん。

ここでDummyPropも作成していますね。

で先程作成した関数に以下の実装を追加しています。

Dummy PropだけTeleportさせています。

これでDummy Propに付属のExplosive Deviceも一緒にTeleportすると思っているですが違うんでしょうか?

この関数を以下の場所に追加しました。

次に以下の赤線の箇所にBomb.Expload()関数を追加しました。

ああ、分かりました。

Bombを車に追加するだけならPropだけで充分なんですが、Bombを爆発させるためにはExplosive Device型のConstantであるBombも必要になると言う訳です。

はい。

理解しました。

<Final Script>

ここでは以下の関数の実装を完成させただけでした。

Spawn:ってどんな機能なんでしょう?

調べます。

うーん。

こんな使用方法は検索に引っかからなかったです。

謎です。

<Setting Up Device with Car, Explosive Device>

UEFNに戻って来ました。

後はVerseで作成したConstantに当てはまるAssetをDeviceにセットするだけです。

Deviceを配置しました。

以下のようにそれぞれのConstantに対応するAssetをセットしました。

<SETTING UP EXPLOSIVE SETTINGS>

ここでExplosive Deviceの設定を変更しています。

Player Damageの値を200に変更しました。

この辺の設定の変更が何故必要なのかはよく分かりません。

これだけのDamageをPlayerに与えるとPlayerが死ぬんでしょうか?

実装した後で確認します。

更にVisible During Gameの値をOnにしました。

この意味は分かります。

爆弾が見えなかったら車が爆発する意味が分かりません。

爆弾がVisibleである方が車が爆発する可能性がある事がPlayerに伝わります。

と思ったらOffにしてしまいました。

うーん。

まあ。どっちでも良いです。

最後にCollision During GameをOffにしました。

これがOffになってないとBombが車と衝突するようになるそうです。

<Final Result>

運転している車の速度が40km/hを下回ったら、

爆発しました。

今週のUEFNの勉強はここまでとします。

実装は来週やります。

Tutorialの実装と私の予測がどれくらい近いのかの検討もやりたかったんですが、もう時間が無くなってしまいました。

来週時間があったらやる事にします。

8.DirectX12の勉強

8.1 Lötwig Fusel氏のD3D12 Beginners Tutorialを勉強する

8.1.1 先週の復習

先週何を勉強したのか全く覚えていません。確か最初のTutorialである Project Setup & ComPointer | D3D12 Beginners Tutorial [D3D12Ez] [11]の実装まで終わったはずです。

先週のBlogを読んで確認します。

違っていました。

終わってなかったです。

先週の勉強内容を以下に簡単にまとめます。

Lötwig Fusel氏の作成したComPointer.hppをComPointer.hとして追加したらErrorになってしまいました。

どこが間違っているのかが分からないのでまずCom Pointerが使用出来るかどうかの確認を行いました。

調べるとCom Pointerは別に何かをしなくても普通に使用出来るそうです。

Com Pointerを使用するにはIUknownを使用します。

以下のようにIUknownを使用すると

特に問題なく使用出来ました。

次にこのIUknown*で宣言したpを使用してRelease()関数を呼び出しています。

Release()関数の機能については以下のような説明がまとめられていました。

次はAddRef()関数についての解説です。

この関数は呼び出されるたびにRef Counterの数を一回増やします。

後、ここで重要な情報を得ていて、それは「Interface PointerをCopyする度に自分でこの関数を使用してRef Countを増やす必要がある」事です。

Com Pointerは自動でRef Counterの数を管理はしてくれない事が判明しました。

これは結構面倒です。

最後にQueryInterface()関数について説明しています。

QueryInterface()関数は以下のように

DeviceはID3D12Device*から作成しました。

でこの関数の機能がいまいち理解出来ないところで終わっています。

8.1.2 QueryInterface()関数の機能について

先週から一週間経って、落ち着いた状態で

公式SiteのIUnknown::QueryInterface(REFIID,void**) method (unknwn.h) [11]にあるQueryInterface()関数の機能を説明した以下の文章を読むと

以下のように解釈出来ます。

DeviceがCom Objectの派生かどうか確認します。DeviceはCom Objectの派生なのでCom Objectです。その場合はAddRef()関数を読んだ後にDeviceのPointerを返します。

ここでInterfaceと言う言葉が混じっているので意味が分かりにくくなっているんです。

Interfaceと言う言葉の定義をしっかり復習してこの文章の意味を完璧に理解します。

GeekforGeekのC++ Program to Create an Interface [12]を読み直しました。

直ぐにC++のInterfaceの仕組みについて思い出しました。

昔この辺の勉強は死ぬほどやったんでした。

ようはVirtual Classの事です。

C++にはInterfaceが存在しないのでVirtual Classで代用するんです。

でVirtual ClassからObjectを直接作成する事は出来ませんので、Com Objectは何かのInterfaceから派生して作られた子Classなはずです。

C++ですので、元になるInterfaceは一つである必要はなく複数のInterfaceからInheritanceする事も可能なはずです。

これがOne of its interfaceの意味と考えられます。

でa PointerはここではDeviceの事を指しています。このDeviceがCom ObjectがInheritanceしたInterfaceを指しているかどうかを調べます。

あ、ここで意味が破綻しました。

C++ではInterfaceから直接Classを作成する事は出来ませんのでPointerがinterfaceを直接指す事は出来ません。

うーん。

私の最初のImageだとCom ObjectというかCom Classはその下に沢山のInterfaceを持っているんです。

そして指定されたPointer(この場合はDevice)の指しているInterface(この場合はID3D12Device)がそのCom Classの下にあるInterfaceの一個である場合は、そのPointerの値を返します。

更にPointerを返した場合は、自動でAddRef()関数を呼び出します。

という意味に取ったんです。

でもC++のInterfaceの定義から考えるとこの訳は間違っていますね。

あれ?

そう言えばID3D12DeviceってInterfaceじゃなかったでしたけ?

ID3D12Deviceを調べれます。

公式のID3D12Device interface (d3d12.h) [12]です。

Interfaceって書いてあるじゃないですか。

やっぱり最初の解釈があってたんです。

うーん。

でもInterfaceからObjectを直接作成する事は出来ないのも正しいはずです。

どういう事?

まあ、良いです。

QueryInterface()関数の機能に関して言えば最初の解釈であってるはずです。

それさえ理解出来れば、今の時点では十分でしょう。

8.1.3  Project Setup & ComPointer | D3D12 Beginners Tutorial [D3D12Ez] [11]の続きを実装する

QueryInterface()関数を実装しました。

IID_PPV_ARGSを使用しています。

これは「DirectX 12の魔導書」の勉強などで何回も勉強しました。

一応、過去のBlogを見て何を勉強したのかを確認します。

2023-02-13のBlogで以下のように述べていました。

これしか勉強してないみたいです。

いや確かIID_PPV_ARGSの公式Siteを調べた記憶があります。

他のBlogでもIID_PPV_ARGSについて勉強しているのかもしれません。

と思ったらこのBlogの下の方に以下の解説がありました。

成程。

これは分かり易い。

公式SiteのIUnknown::QueryInterface(REFIID,void**) method (unknwn.h) [11]のQueryInterface()関数のParameterには

以下の2つがあります。

それぞれ

となっています。

この2つのParameterを一個で代用するのがIID_PPV_ARGSです。

Tutorialを見ると同じような説明をしていました。

最初にTutorialを見た時は理解出来なかったですが、今こうやってある程度の知識の下地が出来た状態で聞いたら、何を説明しているのかよく理解出来ました。

次にCom Classですがそのまま貼り付けていました。

あれ?

これでErrorになったんですけど。と思ったら

TutorialでもしっかりErrorになっていました。

うーん。

どうやってこのErrorを直すんでしょうか?

何とそのままにして使用していました。

えええ。

まあ試してみます。

GitHubから最新のComPointer.hppの実装をCopyして前に作成したComPointer.hにPasteしました。

以下の箇所がErrorになっています。

Fileの位置を整理していたらいつのまにかErrorが消えています。

このComPointer.hを使用するとRef Counterを気にしないでCodeを書く事が出来るそうです。

うーん。

これは便利。

普通に使えました。

はい。

これでこのTutorialの実装は全部出来ました。

来週は次のTutorialを勉強する事にします。

8.2 「DirectX 12の魔導書」の勉強

8.2.1 先週の復習

先週は「4.3 Vertex Buffer」を読んだだけです。

先週のBlogでは

と書いていましたが実際のSpellはCreateCommittedResourceでした。

CommittedがComittedになっていました。

8.2.2 CreateCommittedResource()を実装する

Sample Codeを見ると以下のように実装していました。

順番としてはまずD3D12_HEAP_PROPERTIES型であるheappropを作成し、それぞれの要素の値を指定します。

次にD3D12_RESOURCE_DESC型であるresdescを作成しそれぞれの要素を指定します。

更にID3D12Resource型であるvertBuffを作成します。

これらをParameterとして最後にCreateCommitedResource()関数を呼び出してGPU側のMemoryを確保します。

この順番に実装しながらそれぞれのStructの機能を勉強していくことにします。

丁度教科書もその順番で説明しています。

<D3D12_HEAP_PROPERTIES>

まずは実装してしまいます。

Sample CodeにあるD3D12_HEAP_PROPERTIESの部分をCopyしてそのまま自分のProjectにPasteしました。

Sample CodeではShowWindow()関数の下に実装していたのでそのまま同じ場所にPasteしました。

後、Sample Codeには既に

Verticesの値が指定されていました。

先週、教科書を読んだ限りではVerticesの実装方法の説明はありましたが、実際の実装は無かったはずですがどうしましょう?

別にこの部分は何か勉強しないといけないところは無いので、もし後になっても実装しない場合はその時に実装する事にします。

公式SiteのD3D12_HEAP_PROPERTIES structure (d3d12.h) [13]です。

以下の要素があります。

Sample Codeの実装では4番目と5番目の要素は指定していませんね。

Typeです。

ここで作成されるHeapのTypeを指定するそうです。

公式SiteのD3D12_HEAP_TYPE enumeration (d3d12.h)[14]を見ると

ここで指定出来るHeapのTypeには以下の4つがあるそうです。

Sample CodeではD3D12_HEAP_TYPE_UPLOADが指定されています。

D3D12_HEAP_TYPE_UPLOADの解説を以下に示します。

結構長いですね。

CPU側から一回だけ書き込んでGPU側から一回だけ読み込む目的のHeapに最適の設定のようですね。

それ以上はわかりません。

教科書の「4.3.2 Vertex heapの設定」の説明も読んでおきます。

うーん。

まずBandwidthが何を表してるのかが分かりました。これが広い程Accessするのが速くなります。

D3D12_HEAP_TYPE_UPLOADに関しては教科書でもCPU側から一回だけ書き込んでGPU側から一回だけ読み込む目的では最適のHeap設定と書いていました。

後、残り3つのTypeの特長についてもそれなりに詳しく説明していました。

私は今回使用しないTypeの特長まで勉強する気はありません。

その部分はSkipします。

2番目の要素であるCPUPagePropertyについてです。

公式SiteのD3D12_CPU_PAGE_PROPERTY enumeration (d3d12.h)[15]を読んでみます。

以下の4つの要素があるそうです。

Sample Codeを見るとD3D12_CPU_PAGE_PROPERTY_UNKNOWNが使用されていました。

D3D12_CPU_PAGE_PROPERTY_UNKNOWNの特長については以下のような説明がありました。

うーん。

これだけじゃ何なのか全く分かりませんね。

教科書を読んでみます。

教科書読んだら、これ以降の設定はHeapのTypeがCustomの時だけしか使用しないので初心者は勉強しなくて良いと書いてありました。

はい。

残りはSkipして次にいきます。

<D3D12_RESOURCE_DESC>

これも最初に実装します。

Sample CodeをそのままCopyしました。

あれ?

Errorになっています。

あVerticesのところがErrorになっています。

ここではSizeof(前頂点)と書いてありましたが、その次の節ではSizeof(vertices)と書いてありました。

のでVerticesも追加します。

以下のようにSample CodeをそのままCopyして追加しました。

うーん。

Errorになっています。

教科書の「4.2 頂点情報の作成」を読み直します。

ありました。以下のDirectXMath.hをIncludeしろと書いてありました。

しました。

あれ、したけどErrorのままです。

教科書を読み直したらNamespaceでDirectXを使用するかDirectX:XMFLOAT3と書くようにと書いてありました。

Sample Codeではどうやっているのか確認します。

ありました。

Using namespaceを使用していました。

全く同じにします。

結果です。

Errorが消えました。

D3D12_RESOURCE_DESCのそれぞれの要素については、教科書ではあまり解説していませんでした。

見るとResdescのSizeを指定するための設定のようで前も似たような設定をWindowを作成した時にやりました。

そんなに真剣に勉強する必要はない部分な気もします。

今回はこの部分の設定についての勉強はSkipします。

<ID3D12Resource>

これはSample Codeでは以下のように実装していました。

教科書には特に説明はありませんでした。

同じ様に実装します。

<CreateCommitedResource>

やっとCreateCommitedResource()関数を使用出来る所までやって来ました。

まずはSample CodeをそのままCopyしてProjectにPasteします。

しました。

別にErrorの表示とかもないです。

一応、公式SiteのID3D12Device::CreateCommittedResource method (d3d12.h)[16]を見てみます。

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

この中のParameterで未だによく分からないのは2番目のParameterであるD3D12_HEAP_FLAGSと4番目のParameterであるD3D12_RESOURCE_STATEです。

これらのParameterについて一寸だけ調べます。

まず2番目のParameterであるD3D12_HEAP_FLAGSについてです。

うーん。

説明聞いてもピンと来ません。

D3D12_HEAP_FLAGSを見てみます。

公式SiteのD3D12_HEAP_FLAGS enumeration (d3d12.h)[17]です。

こんなに色んな種類のFlagがあるの?

Sample Codeで使用しているのはD3D12_HEAP_FLAG_NONEですね。

これの特長だけ調べる事にします。

はい。

四番目のParameterであるD3D12_RESOURCE_STATESについても調べます。

公式SiteのID3D12Device::CreateCommittedResource method (d3d12.h)[16]におけるD3D12_RESOURCE_STATESの説明です。

D3D12_HEAP_TYPE_UPLOAD heapを使用する場合はこのParameterの値はD3D12_RESOURCE_STATE_GENERIC_READになると書かれています。

Sample Codeのこの値は

になっていました。

こんだけ理解したら今は十分です。

はい。

最後に教科書ではこの関数がきちんと動いているかどうかをResultにS_OKが返っているかどうかで確認しろ。と書いてありました。

これをやります。

以下のCodeを追加してテストします。

Sample Codeを実行します。

何も表示されません。

出来てるようです。

念のため、以下の箇所にBreak Pointを設置してResultの中身を確認しました。

結果です。

S_OKになっていました。

出来ています。

今週の「DirectX 12の魔導書」の勉強はここまでとします。

9.まとめと感想

なし。

10. 参照(Reference)

[1] Castle Wall Tool. (n.d.). https://www.youtube.com/playlist?list=PLNbgmFvU__fiPhyUWHHzZ2Nv5ieM_bOdB

[2] Rectangular area lights. (n.d.). https://docs.unrealengine.com/5.3/en-US/rectangular-area-lights-in-unreal-engine/

[3] Reflections captures. (n.d.). https://docs.unrealengine.com/5.3/en-US/reflections-captures-in-unreal-engine/

[4] Ryan Manning. (2021, May 25). UE4 Reflection Captures - How-to Use [Video]. YouTube. https://www.youtube.com/watch?v=KEwZD3hgX2o

[5] Gediminas Kirdeikis. (2023, April 30). Unreal Engine 5 for Architecture - 2023 Full Beginner Course [Video]. YouTube. https://www.youtube.com/watch?v=bT8aSTkpkDY

[6] Niagara Debugger. (n.d.). https://docs.unrealengine.com/5.3/en-US/niagara-debugger-for-unreal-engine/

[7] Ben Cloward. (2023, April 27). Local Volumetric Fog - Advanced Materials - Episode 23 [Video]. YouTube. https://www.youtube.com/watch?v=En-VjBjto_U

[8] Rick Banks. (2022, June 20). Houdini 19 - Wall Tool 02 [Video]. YouTube. https://www.youtube.com/watch?v=J2Tf_OIy9CA

[9] Which licenses are needed to run which product? | SideFX. (n.d.). https://www.sidefx.com/faq/question/which-license-strings-are-required-for-each-houdini-product/

[10] Pi Equals Three. (2023, April 16). If I Don’t Drive Above 40, The Bomb will Go Off! Fortnite UEFN/Creative 2.0 Tutorial [Video]. YouTube. https://www.youtube.com/watch?v=rt_S-GfWstY

[11] Stevewhims. (2022, August 31). IUnknown::QueryInterface(REFIID,void) - Win32 apps. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(refiid_void)

[12] Stevewhims. (2023, February 14). ID3D12Device (d3d12.h) - Win32 apps. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nn-d3d12-id3d12device

[13] Stevewhims. (2021, April 2). D3D12_HEAP_PROPERTIES (d3d12.h) - Win32 apps. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_heap_properties

[14] Stevewhims. (2023, February 14). D3D12_HEAP_TYPE (d3d12.h) - Win32 apps. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_heap_type

[15] Stevewhims. (2022, January 31). D3D12_CPU_PAGE_PROPERTY (d3d12.h) - Win32 apps. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_cpu_page_property

[16] Stevewhims. (2021, October 13). ID3D12Device::CreateCommittedResource (d3d12.h) - Win32 apps. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-createcommittedresource

[17] Stevewhims. (2023, February 14). D3D12_HEAP_FLAGS (d3d12.h) - Win32 apps. Microsoft Learn. https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_heap_flags