Blog banner

GUIを超えて

フードの下で何が行われているかを理解することは、決して損にはならないだろう?コンピュータ・グラフィックスのための低レベルAPIであるVulkanに初めて触れたときのことを見てみよう。

  • Erick Frederick
  • 9 ヶ月前
  • ゲーム開発

前回のブログポストでは、手短に自己紹介をし、趣味であるゲーム開発にどのようにのめり込んだかについて書きましたが、アンリアル・エンジンでその時欲しいものを作ることができる一方で、何かが欠けていました。

ソフトウェア開発のキャリアをスタートさせたときから、まったく新しい分野を学ぶときにはいつも奇妙なアプローチをしてきた。つまり、まず簡単な道(フレームワークやライブラリ)を選んでから、実際に何が起こっているのかを理解するためにボンネットの下に潜り込むという方法だ。このアプローチを取ることは、コードの各ブロックが何をしようとしているのか、その期待される結果を知ることでおおよそわかるので、私にとってはかなり効果的だった。

文脈

表面的には、画面に表示されるすべてのものを司るコンピュータの部品である:

  • CPU:

    • 非常に高速にコマンドを実行する。
  • GPU:

    • CPUをサポートするが、速度は遅い;
    • コア数が多いため、より大きなデータセットに対応できる。

CPUを制御するためには機械語を使ってコミュニケーションする必要があるが、最近では人間から機械語に翻訳するツールがある。

CPU(私の理解ではx86/x64)は、タスク実行を助けるためにGPUを自動的に使用しないことが判明した。低レベルのプログラミングを使って直接行うか、抽象化するAPIを使うかのどちらかだ。

今のところ、ゲーム開発で最もよく使われているAPIはこれです:

  • Vulkan;
  • DirectX 11 / 12;
  • Metal;
  • OpenGL.

バルカン は最初から選択するのは良くないと何度も見ていたにもかかわらず、私はとにかくそれを選択した。

スタート

Vulkanを始めるのは本当に圧倒される経験で、その時(1ヶ月前)は、スクリーンで何かを見れば少しは良くなるだろうと思っていました。新しい技術を学ぶのはこれが初めてで、最終的に自分の仕事の成果物を見るのに、およそ1k行のコードが必要だった。

まず、Vulkan Tutorialに従って、ゲーム開発 A Triangle の "Hello World "を作ることができました。

私は新しい技術を使いこなすのが大好きだが、新しい分野となると、基礎をしっかり学べるようなアカデミックなアプローチを取りたくなる。

自動生活

コンピューターグラフィックスに関する知識不足が災いして、無心にコードをコピーして配置するばかりで、自分が何をしているのかよく理解していなかった。

今の教材は、何をなぜやっているのかを説明するのに優れていますが、1つの教材ではそこまでしか説明できないので、時にはCGの教材とリンクしてしまうこともありました。そこで、Vulkanで描画がどのように動作するのかをyoutubeで検索することにしました。そこで、GetIntoGameDevのyoutubeチャンネルとVulkan CPPシリーズに出会いました。

私にとっては完璧でした。まず、私はそれまでCしか使っていなかったので、VulkanにC++のバリエーションがあることを知りませんでしたし、GetIntoGameDevの教え方はCGの面でも説明が早かったです。

再スタート

そのため、現在の進捗状況をすべて消去し、素材となるコード・スニペットに従いつつ、自分なりの方法で書くという、新しいアプローチを念頭に置いていました。最近、レーシング、特にシミュレーション・レーシング(シム・レーシング)にハマっていて、プロジェクト名もそれにちなんだChicaneというテーマなんだ。

だから、当時持っていた知識で自分のエンジンを大まかに設計することにしたんだ:

基本的なアプリケーションの設計とはいえ、私が最初に作るのはゲームではなく、本質的にゲームを作るための視覚的に重いツールであるChicaneの概要であるという事実を考えると、かなり大胆でもあります。

この設計では、すべてのVulkan APIの使用をRuntimeに集中させ、EditorにはSceneとして知られるレンダリング空間内のインスタンスの追加、変更、削除のみを任せることになります。

3Dオブジェクトのレンダリングなど、いくつかのハプニングもあった。

期待される結果を知らなくても、その大まかな形ははっきりわかるが、なぜ三角形の形が崩れたり、完全に欠けてしまったりするのかは、私の悩みの種だった。犯人は?

    outAllocationSize =+ sizeof(*mesh[0]) * allocationInfo.vertexCount;

このコード・スニペットは、意味的にも構文的にも有効なので、コンパイラー・エラーや警告を引き起こすことはない。修正方法は?

より

    =+

    +=

デバッグとリファクタリングが、ほぼ3日間私がしていた唯一の活動でした。コードベースに関する知識が増えたことで、この厄介なバグを見つけて修正することが可能になりました。

彼の

    std::vector<float> vertexData = {
        texturePosX, texturePosY,
        positionX, positionY, positionZ,
        colorR, colorG, colorB,
        normalPositionX, normalPositionY, normalPositionZ
    };

僕の

    struct Instance
    {
        glm::vec3 position;
        glm::vec3 color;
        glm::vec2 texturePosition;
        glm::vec3 normal;
    };

もちろん、いくつかの実装は少し難しくなりましたが、そのような変更はチュートリアルを進めていく上で本当に役に立つことが証明されましたし、チュートリアル・シリーズの後半で同じようなリファクタリングを行ったものもありました。

未来

今日現在、これがプロジェクトの現状だ。

最初の頃から、大きなコード変更のたびにパフォーマンスの変化をチェックしていたんだけど、最近はリサイズや最小化・最大化などのウィンドウ・イベントの処理に関連するメモリ・リークを修正しようとして行き詰まっている。

このプロジェクトを実験として扱うのか、それとも本当に集中するのか、時間が経たないとわからない。

キューブマップなど、チュートリアルを "完成 "させるために実装しなければならないものがまだいくつかある。今年も終わりに近づき、オフの時間が必要だ。

あけましておめでとうございます!