超雑訳 Adventures with Deferred Texturing in Horizon Forbidden West

こんるるー。
Pocolです。
今日は…
[McLaren 2022] James McLaren, “Adventures with Deferred Texturing Horizon Forbidden West”, GDC 2022.
を読んでみようと思います。
いつもながら誤字・誤訳があるかと思いますので,ご指摘頂ける場合は正しい翻訳と共に指摘していただけると有難いです。
断りが無い限り,図は[McLaren 2022]からの引用です。

(さらに…)

Game Boy 研修(2)

今日は,エミュレーターの実装の進め方について紹介します。

基本的には…
MJHDというのブログ記事の「Rustでゲームボーイエミュレータを自作した話」に沿った手順で実装するのが良いと思います。
また,どのよう実装するかイメージがつかめない方は「脱・初級者のための自作GBエミュレーター開発」というスライドを参考にするものよいかもしれません。

Step.1 ROMをデコードする
Step.2 CPU処理を実装する
Step.3 PPU処理を実装する
Step.4 デバッガを実装する
Step.5 CPUテストROMを通す
Step.6 機能追加・改善を考え,実装する。

ROMをデコードする

まずは,ゲームボーイのソフト。つまりカートリッジデータが読み込みできなければ話になりません。
…なので,まずはカードリッジデータを読み込めるようにしましょう。カードリッジデータが読み込めれば,ゲームで使用する命令列などが読み取れるようになるはずです。
カートリッジのデータフォーマットなどについては,Pan Docs にまとまっているようなので,どういうデータ構造になっているのか?についてはドキュメントを読みましょう。
どんなプログラマーもドキュメントが読み解けるようにならなければいけません。特に,コンソールプラットフォームなどは秘密事項の塊で,インターネットに情報が出ることはめったになく,公式ドキュメントを見なければ何も出来ないということが多々あります。
そのため,ドキュメントを見ながら実装力をつける訓練の最初の一歩としてやってみましょう。

CPU処理を実装する

続いて,絵を出す前にCPU処理をエミュレートした方が良いでしょう。
ロード命令やジャンプ命令・加算・減算・ビット演算など基本的な命令を実現できるようになりましょう。
また,基本的な命令の実装を通じて,低レベルで何が行われるのか?を知ることが研修の目的の一つでもあります。

PPU処理を実装する

グラフィックスプログラマーを目指すものであれば,絵が出せなければいけません。また,やっぱりゲームは絵が出てこそ!というところもあるので,絵を出しましょう。
また、PPU(Picture Processing Unit)で何が行われているかを知りましょう。これを知るためには,PPU処理を実装するのが一番です。
PPU処理の実装が出来れば,一番処理にGame Boyプログラムで作った「Hello World」の文字列表示プログラムが動かせるようになるはずです。

デバッガを実装する

PPU処理まで実装出来たら,あとはひたすら精度・品質を上げていくだけです。
そのためには,デバッガの実装は必須でしょう。
また,デバッガを実装するためにどのようなことをしなければないのか,普段我々がVisual Studio何気なくつかっているブレークポイントなどの機能はどのようにしておこなわれているのか?などデバッガの仕組みを身をもって体験してください。

CPUテストROMを通す

最後の仕上げです。
実機で動作保証がされているCPUテストと呼ばれるROMを実行し,自作のエミュレーターで正常動作すること確認してください。
テストのROMは以下にあります。
https://gbdev.gg8.se/files/roms/blargg-gb-tests/
正常動作しない場合は,エミュレーターの実装に問題があるということです。
特に会社等では,テスト駆動開発を実施している会社もあるのと思うので,ここでテストの重要さ,製品の品質保証など,クオリティーを上げる大事さを学んでください。

機能追加・改善を考え,実装する

言われた仕様,あるいはお題に通りに作れば最低ラインは超えたことになります。少なくとも一般的な会社では言われたこと通りものを作ることが出来れば,きちんと給料は支払われるはずです。
ここから先は,「他とどう差別化するか?」という話です。同じ機能でも見た目をカッコよくできるのであれば,付加価値はあがるでしょう?また,他社や他人には出来ない機能追加をするのもよいかもしれません。あるいは,思い切って機能を削ることによる分かりやすさの改善・動作安定性なども差別化が図れるでしょう。
余力がある人は,自分なりのカラーを出せるように改造・改変してみてください。
特に昨今はKFCの事例のように何も考えない会社が作るとUX(User Experience:ユーザー体験またはユーザー体感)が激悪化しやすいです。また,どことはいいませんが解約手続きの面倒さなど,もう二度と使うもんか!と思うような酷いものあったりします。ユーザーにとって何か使いやすいのか?何が嬉しいのか?については我々は常に思考を巡らせる必要があります。特に日本の大手会社(例えば電機メーカーなど)などはこうした考えが非常に弱く,そのせいで海外メーカーにシェアを取られるというひどい状況に陥っています。携帯電話のUXの酷さなどはそのもっともたる例のひとつになるかもしれません。
我々はグローバルに戦っていく必要があります。そのためは,常にユーザーないし,使う側の立場にとって良いものを提供する必要があると思います。
そこで,余力がある人は作ったアプリに対して,ユーザーにとって有益であるような機能追加・機能改善を実行してみてください。
恐らく基本となる考え方は「自分だったら嬉しいか・喜ぶか」がベースになるのではないかと思います。そこから,平均と比べて自分がどのぐらいズレがあるのかを推測して補正していくと良いでしょう。

超雑訳 Shadow Techniques from Final Fantasy XVI

こんちゃわ。
Pocolです。

今日は…
[Fatnassi 2023] Sammy Fatnassi, “Shadow Techniques from Final Fantasy XVI”, Technical Report, Square Enix, 2023, http://www.jp.square-enix.com/tech/publications.html.
を読んでみようと思います。

いつもながら誤字・誤訳があるかと思いますので,ご指摘頂ける場合は正しい翻訳例と共に指摘していただけると有難いです。
(さらに…)

Game Boy 研修 (1)

こんにちわ。Pocolです。
今年は研修どうしようか悩んでいたんですが,今の若い人はあんまりハードのことを知らないのではないか?(当然、めっちゃ詳しい人もいますが…)
という考えが湧いてきたので,今年はGame Boyでプログラミングするというのを研修ネタとしてやってみようかなと思います。

目的

ハードウェアについて理解し,実際にゲームを作成し,プログラミング能力および開発能力を高める。
また、ポーティング作業を行うことでマルチプレットフォーム展開を行う際に、やってはいけないことを体感させ,開発効率改善および向上のための意識づけを行うことを目的とする。
エミュレーター開発を通じて各種APIへの理解を深める。

目標

  • 開発環境を自分で整えられるようになる。
  • Game Boy上で動くゲームを自力で開発する。
  • Game Boyエミュレーターを自作し,ハードウェアを理解する。
  • 指定されたプラットフォーム上で動作するように自作したGame Boyエミュレーターの移植作業を行う。

資料

● The Ultimage Game Boy Talk

● The Game Boy, a hardware astopsy – Part 1: the CPU

● The Game Boy, a hardware autopsy – Part 1.5: a few mistakes and register F

● The Game Boy, a hardware autopsy – Part2: Memory mapping

● GBDKの導入~ゲーム作成まで
https://qiita.com/BubbleBubble/items/9c28c57ed942c9b48843

● きるこ日記帳
https://www.dkrk-blog.net/category/GameBoy

● ゲームボーイのゲームを作ってみる
https://www.youtube.com/watch?v=xhUOhT7KKE4&list=PLbP78mBX9wpCH1SwnLix14rd1g47XJ5fO

● Game Boy Development community
https://gbdev.io/

● Open Game Boy Documentation Project
https://mgba-emu.github.io/gbdoc/

スケジュール

● 第1週目
お題:指定されたライブラリを利用した開発環境を整えてください。そして,第3者が開発環境を整えられるように手順書を作成してください。
アドバンスなお題:Visual Studio Codeで開発できるようにしてください。

● 第2~3週目
お題:サンプルアプリを作ってください。
  ・Hello, Worldの表示
  ・スプライト描画
  ・十字キー入力でキャラを動かす
  ・音を鳴らす (Option)
  ・説明書を作る (Option)

● 第4週~第5週目
お題:Game Boyエミュレータを自作して,サンプルアプリを動かしてください。ただし、描画APIを利用する場合はDirectX12を使用してください。
※6週目~7週目を見越してラッパーAPIを作っておくのは可とします。
アドバンスなお題:
  ・ゲームパッド対応を行ってください。
  ・どこでもセーブできる機能を作ってください。
  ・アップスケール対応を行ってください(Option) [ex]Hq3xなど…
  ・可能であれば次のSIGGRAPH論文を実装してしてください(Advanced)
    Johannes Kopf, Dani Lischinski, “Depixeling Pixel Art”, SIGGRAPH 2011 Technical Papers, https://johanneskopf.de/publications/pixelart/
    実装参考として,次のPythonコードを参照するのは可とします。https://github.com/vvanirudh/Pixel-Art
補足:動作確認には自作のアプリとhttps://gbdev.gg8.se/files/roms/blargg-gb-tests/のROMが動作することを確認してください。

● 第6週~第7週目
お題:指定プラットフォーム上で,自作Game Boyエミュレータを動作するように移植作業を行い,サンプルアプリを動かしてください。

1-Phase Occlusion Culling

完全に私的な実装メモです。
通常,オクルージョンカリングを実装する際は,GPU Zenやもんしょさんのサイトに載っているように2-Phaseでジオメトリ描画して実装するのが普通かと思います。
少し前ですが,GDC 2021の“Samurai Landscapes: Building and Rendering Tsushima Island on PS4”というセッションの,43:45あたりから,Occlusion-Cullingについての説明があり,Ghost of Tsushimaの実装では,前フレームの深度バッファと,それらから保守的(conservative)に作成したミップレベル,エピポラーサーチを用いて,現在フレームの深度バッファを復元し,1回のジオメトリ描画でオクルージョンカリングを実装する方法が紹介されています。
説明が分かりやすいので,アルゴリズムについては元動画を参照してください。
馬鹿まじめに線形探索をせずに,ミップマップを使って検索するのがアルゴリズムのキモみたいです。

一応実装コードが紹介されていますが,動画の品質が低すぎて全然良く見えませんw。
そこで,それっぽい感じに見えるコードを自分で推測しながら書いてみました。
推測で書いているのと,きちんと動作検証もしていないので,バグっている可能性があるので,まんまコピペで使用して不都合・不利益が発生しても何ら責任は負いませんのでご注意ください。
もし、「ここはこうじゃね?」とかアドバイスあればコメントください。

Depth Reprojection

// Forward-project last frame's depth to this frame's space
{
    float zPrev = pSrt->m_texIn[dispatchThreadId.xy];
    float zDepthPrev = DepthFromWorld(zPrev, pSrt->m_vecRecoryHypebolicDepth);

    float4 posClipPrev = float4(VecClipFromUv(uvThread), zDepthPrev, 1.0f);
    posClipPrev *= zPrev; // This ensure that zCur will end up in posClip.w;

    float4 posClip = mul(posClipPrev, pSrt->m_matClipPrevToClipCur);
    posClip.xyz /= posClip.w;

    float2 uv = UvFromVecClip(posClip.xy);

    if (all(uv >= pSrc->m_rectScissor.xy) && all(uv >= pSrc->m_rectScissor.zw))
    {
        // NOTE : z ends up in posClip.w so we can use that directly.
        float z = posClip.w;
        
        if (z < pSrt->m_zNear)
            z = pSrt->m_zFar;

        // NOTE : Add a small bias to resolve self-occlusion artifacts
        z += pSrt->m_dsBias;

        if (z > pSrt->m_zFar || zPrev >= pSrt->m_zFar)
            z = pSrt->m_zFar;

        float2 xy = floor(uv * pSrt->m_texture.m_dXy); // 多分、テクスチャサイズを乗算してウィンドウサイズに戻している。
  
        AtomicMax(pSrt->m_texOut[xy], z);
    }
}

{
     float4 posClip = float4(VecClipFromUv(uvThread), 0.0f, 1.0f);

     float4 posClipPrev = mul(posClip, pSrt->matClipCurToClipPrev);

     if (any(abs(posClipPrev.xy) >= abs(posClipPrev.w))
     {
          float2 uv = UvFromVecClip(posClipPrev.xy / posClipPrev.w);

          float z = pSrt->m_texIn->SampleLOD(pSrt->m_sampler, uv, 0) * pSrt->m_dsBias;

          AtomicMax(pSrt->m_texOut[dispatchThreadId.xy], z);
     }
}

Hole-Filling

float2 uv = (dispatchThreadId.xy + 0.5f.xx) * pSrt->m_texture.m_div;
float zMax = pSrt->m_texIn.SampleLOD(pSrt->m_sampler, uv, 0);

if (zMax == -FLT_MAX)
{
    float2 normalEpipole = normalize(pSrt->m_uvEpipole * uv);
    float2 dUvStep = pSrt->m_texture.m_div * normalEpipole;

    for(uint iMip = 1; iMip <= pSrt->m_iMipLast; ++iMip)
    {
        float2 uvSearch = uv - dUvStep;
        dUvStep *= 2.0;

        float z = pSrt->m_texIn.SampleLOD(pSrt->m_sampler, uvSearch, iMip);

        if (z != -FLT_MAX)
        {
            z = max(z, pSrt->m_texOut[dispatchThreadId.xy]);
            z *= pSrt->m_dsBias;
            z = min(z, pSrt->m_zFar);
            pSrt->m_texOut[dispatchThreadId.xy] = z;

            return;
        }
    }

    if (zMax < pSrt->m_zNear)
        zMax = pSrt->m_zFar;

    zMax = min(zMax, pSrt->m_zFar);

    pSrt->m_texOut[dispatchThreadId.xy] = zMax;
}

超雑訳 HypeHype Mobile Rendering Architecture

こんねね~。Pocolです。
今日は…
[Aaltonen 2023] Sebastian Aaltonen, “HypeHype Mobile Rendering Architecture”, SIGGRAPH 2023 Advances in Real-Time Rendering in Games course.
を読んでみようと思います。
いつもながら誤字・誤訳があるかと思いますので,ご指摘頂ける場合は正しい翻訳例と共に指摘して頂けるとありがたいです。
特に断りが無い限り,図は[Aaltonen 2023]からの引用となります。予めご認識ください。

(さらに…)

超雑訳 CSM Scrolling, An acceleration technique for the rendering of cascaded shadow maps

こんちゃ!
Pocolです。
今日は…
[Acton 2012] Mike Acton, “CSM Scrolling, An acceleration technique for the rendering of cascaded shadow maps”, SIGGRAPH 2012 Advances in Real-Time Rendering in Games course.
を読んでみようと思います。
いつもながら、誤字・誤訳があるかと思いますので,ご指摘頂ける場合は正しい翻訳例と共に指摘して頂けるとありがたいです。

(さらに…)

超雑訳 Improved Culling for Tiled and Clustered Rendering Call of Duty Infinite Warfare

こんねねー。Pocolです。
今日は,
[Drobot 2017] Michal Drobot, “Improved Culling for Tiled and Clustered Rendering Call of Duty Infinite Warfare”, SIGGRAPH 2017 Advances in Real-time Rendering in Game course, 2017.
を読んでみようと思います。

いつもながら誤字・誤訳があるかと思いますので,ご指摘頂ける場合は正しい翻訳例と共に指摘して頂けると有難いです。
また,特に断りが無い限り,図は[Drobot 2017]からの引用になります。

(さらに…)

GDC 2023関連

こんにちわ、Pocolです。
GDC 2023関連の情報をまとめていなかったので,(FreeContentsで)興味ある資料をまとめておこうと思います。