独創アプリ開発日記 247〜249日目 Steamにおける開発環境

私の今の目標は、Steamでマルチプラットフォーム対応のゲームを公開することです。

出来れば共通のソースコードで各種環境に対応させたいと考え、先日、.NET CoreとOpenTKを使って、Mac/Linux(Ubuntu)/Windowsの各種環境で動作するOpenGLの共通ソースを書きましたが、この方法ではダメなようです。書き上げてから判明しました。

Steamでゲームを公開する際、Linux(Ubuntu)やMacに関しては利用できるライブラリが決まっており、.NET Coreなどは使えません。多分。

結論としては、C++でOpenGLを利用する形で行けば大部分は大丈夫な気がしています。

DirectXは論外です。Windowsでしか動きません。スマホ/Mac/Linuxが対象外になってしまいます。

と言うわけで、直近での次の作業はC#で書き上げたソースをC++に変更することとしました。その際、C++からOpenGLを利用するためfreeglutを使います。GUIに関してOpenTK(GameWindowクラス)は使えないので、GLFWなども利用予定です。

独創アプリ開発日記 224〜246日目 環境に依存しない3D描画

遂に成し遂げました。

海外に武者修行へ1年間行った結果、Unityなどのツールを使わずに、共通のソースコードでMac,Ubuntu(Linux),Windowsの各種環境において3D図形を描画することに成功しました!Write once, run anywhere!

・・・いや、違いました。.NET Core上でOpenTKを使っただけでした。

以下が環境に依存せず動く3D描画PGです。

https://github.com/ukaapple/cubeTest-OpenTK/blob/master/CubeInsWindow.cs

立方体を100x100x100で、合計100万描画します。

TriangleStripで、かつ Instancing使っているので高効率です。メモリ12MB程度しか使わずに済んでいます。

TriangleStripに関しては、過去の日記で記述しています。こんな感じでテクスチャを貼るやり方のことです。

InstancingとはOpenGLの用語で、同じ形状を、位置情報だけいっぱい与えていろんな場所に描画することです。描画速度向上や使用メモリ量削減が期待できます。

一個

千個

百万個は実際にソースコードを動かして確認して下さい。UbuntuやMacではライブラリのインストールが必要です。README.mdを参照して下さい。

目が痛くなることを保証します。

ちなみにInstancingを使わないとメモリ使用量が340MBに跳ね上がります。以下が使わない場合のソースです。

https://github.com/ukaapple/cubeTest-OpenTK/blob/master/CubeWindow.cs

以下のコードで CubeInsWindow を CubeWindow に変更すると、Instancingを使わない描画に切り替えることが出来ます。

https://github.com/ukaapple/cubeTest-OpenTK/blob/master/Program.cs

また、コンストラクタ引数の100の部分を変更することで描画する立方体の数を変更することが出来ます。あまりに描画数を多くしすぎてマシンのメモリを使い果たさないように気を付けて下さい。

タイトルバーにfpsを表示するようにしてるので、OpenGLのベンチマーク目的でいろんな環境で実行するのも良いかもしれません。

.NET CoreでSystem.Drawingを使う Ubuntu編

Ubuntuにおいて、.NET CoreでSystem.Drawing配下のライブラリを扱う方法を記述します。
OpenTKにおいて、テクスチャなどを扱う際に必要です。

UbuntuでSystem.Drawing配下のライブラリ利用時に、以下のようなエラーが発生した場合の対処方法となります。

例外が発生しました: CLR/System.TypeInitializationException
An unhandled exception of type ‘System.TypeInitializationException’ occurred in System.Drawing.Common.dll: ‘The type initializer for ‘Gdip’ threw an exception.’
Inner exceptions found, see $exception in variables window for more details.
Innermost exception System.DllNotFoundException : Unable to load DLL ‘libgdiplus’: The specified module could not be found.


$ sudo apt-get update
$ sudo apt-get install libgdiplus

これだけ!
macに比べるととっても簡単です。

.NET CoreでSystem.Drawingを使う mac編

OS Xにおいて、.NET CoreでSystem.Drawing配下のライブラリを扱う方法を記述します。
OpenTKにおいて、テクスチャなどを扱う際に必要だったので・・・

まずは、X11をインストールします。ここからdmgをダウンロードしてインストールします。

インストール後はシンボリックリンクを貼っておきます。


ln -s /opt/X11/include/X11 /usr/local/include/X11

VSCodeを立ち上げ、Shift(⇧)+Command(⌘)+Pを押して “nuget” と打ちます。リストから「NuGet Package Manager: Add Package」を選択します。※NuGetインストール済みを想定

続いて “System.Drawing.Common” と打ってリターンキーを押下し、「System.Drawing.Common」を選択します。すると、インストール可能なバージョンリストが表示されるので選びます。特に理由がなければいちばん新しいバージョンを選びます。

次に、ターミナルからlibgdiplusをインストールします。事前に色々な依存ライブラリを入れてから、ソースを持ってきてメイク&インストールです。エラーやワーニングが出るかもしれません。柔軟に対応する必要があります。


$ brew install autoconf 
$ brew install pkg-config 
$ brew install readline 
$ brew install automake 
$ brew install gettext 
$ brew install glib 
$ brew install intltool 
$ brew install libtool 
$ brew install cairo
$ brew install jpeg
$ brew install libtiff
$ git clone https://github.com/mono/libgdiplus.git
$ cd libgdiplus
$ CPPFLAGS="-I/usr/local/opt/libpng12/include -I/opt/X11/include" LDFLAGS="-L/usr/local/opt/libpng12/lib -L/usr/X11/lib" ./autogen.sh
$ ./configure
$ make && make install

独創アプリ開発日記 220日目 友愛

 
 
       ノ´⌒ヽ,,
    γ ⌒´    ヽ,
   / /  “”⌒ ⌒ \   )
    i/    ⌒  ⌒ ヽ    )   
    !゙  (・ )` ´( ・)i/
     |   (__人_)  |
   \    `ー’   /
    /         \
 
先日赤坂の通りを歩いていたら、すれ違いざまに怖い形相で「ルーピー」と叫んで立ち去った方がいた。

独創アプリ開発日記 219日目 ポッポ

    / |ミ  パカッ
   /  |  ミ
  |   |
   \  |       スカッ
     \|_______
    i/    ⌒  ⌒ ヽ    )   
    !゙  (・ )` ´( ・)i/
     |   (__人_)  |
   \    `ー’   /
    /         \

独創アプリ開発日記 218日目 環境に依存しないWindow

ここまでで、C#によるOpenGLの開発環境が整いました。

今回は、GameWindowという、Mac/Linux/Windowsのいずれの環境でも動作するウィンドウ表示のコードを書きたいと思います。

このブログでの実際の開発はUbuntu上で進める予定ですが、Macや憎っくきWindows上でも開発可能な想定です。


using System;
using OpenTK;

namespace FloatingIsland
{
    class FloatingIsland
    {
        static void Main(string[] args)
        {
            GameWindow gw = new GameWindow();
            gw.Run();
        }
    }
}

これだけ!”FloatingIsland”は私が開発しようとしている新しいアプリ名です。

実行したら以下のエラーが出ました。’gbm’がロード出来ないようです。


例外が発生しました: CLR/System.TypeInitializationException
An unhandled exception of type 'System.TypeInitializationException' occurred in OpenTK.dll: 'The type initializer for 'OpenTK.DisplayDevice' threw an exception.'
 Inner exceptions found, see $exception in variables window for more details.
 Innermost exception 	 System.DllNotFoundException : Unable to load DLL 'gbm': The specified module or one of its dependencies could not be found.
 (Exception from HRESULT: 0x8007007E)
   at OpenTK.Platform.Linux.Gbm.CreateDevice(Int32 fd)
   at OpenTK.Platform.Linux.LinuxFactory.SetupDisplay(String gpu, IntPtr& gbm_device, IntPtr& egl_display)
   at OpenTK.Platform.Linux.LinuxFactory.CreateDisplay(IntPtr& gbm_device, IntPtr& egl_display)
   at OpenTK.Platform.Linux.LinuxFactory.get_gpu_fd()
   at OpenTK.Platform.Linux.LinuxFactory.CreateDisplayDeviceDriver()
   at OpenTK.DisplayDevice..cctor()

GBMとは:

Generic Buffer Management(GBM)は、Mesaに関連付けられたグラフィックスレンダリング用のバッファを割り当てるためのメカニズムを提供するAPIです。

Mesaとは:

Mesa3DとMesa 3D Graphics Libraryとも呼ばれるMesaは、OpenGL、Vulkanなどの仕様のオープンソースデバイスドライバとソフトウェア実装です。 Mesaは、これらの仕様をさまざまなベンダー固有のグラフィックハードウェアドライバに変換するクロスランゲージ、クロスプラットフォーム(主にBSDおよびLinux)の標準APIを実装しています。

‘gbm’を入れるには以下のコマンドを叩きます。


$ sudo apt-get install libgbm-dev

再度実行すると、またエラーが出ました。次は’libEGL.dll’がロード出来ないとのことです。


例外が発生しました: CLR/System.TypeInitializationException
An unhandled exception of type 'System.TypeInitializationException' occurred in OpenTK.dll: 'The type initializer for 'OpenTK.DisplayDevice' threw an exception.'
 Inner exceptions found, see $exception in variables window for more details.
 Innermost exception 	 System.DllNotFoundException : Unable to load DLL 'libEGL.dll': The specified module or one of its dependencies could not be found.
 (Exception from HRESULT: 0x8007007E)
   at OpenTK.Platform.Egl.Egl.GetDisplay(IntPtr display_id)
   at OpenTK.Platform.Linux.LinuxFactory.SetupDisplay(String gpu, IntPtr& gbm_device, IntPtr& egl_display)
   at OpenTK.Platform.Linux.LinuxFactory.CreateDisplay(IntPtr& gbm_device, IntPtr& egl_display)
   at OpenTK.Platform.Linux.LinuxFactory.get_gpu_fd()
   at OpenTK.Platform.Linux.LinuxFactory.CreateDisplayDeviceDriver()
   at OpenTK.DisplayDevice..cctor()

EGLとは:

EGLは、KhronosレンダリングAPI(OpenGL、OpenGL ES、OpenVGなど)と基本的なネイティブプラットフォームのウィンドウシステムとの間のインターフェイスです。 EGLはグラフィックス・コンテキスト管理、サーフェス/バッファー・バインディング、レンダリング同期を処理し、「他のKhronos APIを使用して高性能で高速化された混合モードの2Dおよび3Dレンダリング」を可能にします。EGLは非営利の技術コンソーシアムKhronos グループによって管理されています。

Khronosとは:

Khronos Groupは、アメリカの非営利団体。 様々なプラットフォームやデバイスの上で動作する、並列計算やグラフィックス、メディア用アプリケーションプログラミングインタフェース (API) のロイヤリティーフリーでオープンな標準規格を作成することを目的としている技術コンソーシアムである。

Khronosの策定する代表的な規格に、3DCG向けAPIであるOpenGL、GPGPUなどのヘテロジニアス・コンピューティング向けAPIであるOpenCLなどがある。

KhronosのメンバーはKhronosの策定するAPI仕様の開発に参加することができ、公開前の投票権を持ち、また(自身のプラットフォームやデバイスでそれらの規格を実装するための)規格草案および規格適合性試験への早期アクセスを通じて自身のプラットフォームおよびアプリケーションの提供を早めることができる。

以下のコマンドを叩きます。


sudo apt-get install libegl1-mesa-dev

実行すると以下のようなウィンドウが表示されます。Ubuntuで実行していますが、MacやWindowsでも同じコードで動作します。

大手には作れないアプリを(気持ちだけは(๑•̀ㅂ•́)و✧)