クロスプラットフォームのレンダラーを書いています。Windows、Linux、Android、iOSで使いたいです。
絶対的な抽象化を避けて、OpenGL ES 2.0で直接書き込むのは良い考えだと思いますか?
私の知る限り、コンテキストとウィンドウシステムへの接続を処理するコードを少し変更するだけで、標準のOpenGLに対してPC上でコンパイルできるはずです。
クロスプラットフォームのレンダラーを書いています。Windows、Linux、Android、iOSで使いたいです。
絶対的な抽象化を避けて、OpenGL ES 2.0で直接書き込むのは良い考えだと思いますか?
私の知る限り、コンテキストとウィンドウシステムへの接続を処理するコードを少し変更するだけで、標準のOpenGLに対してPC上でコンパイルできるはずです。
絶対的な抽象化を避けて、OpenGL ES 2.0 で直接記述した方がよいと思いますか?
これに関する主な問題は、実際には OpenGL 2.1 と同じではない ES 2.0 仕様の部分を扱うことです。
たとえば、ES 2.0 シェーダーをデスクトップ GLSL 1.20 コンパイラーに押し込むことはできません。ES 2.0 では、精度の指定などを使用します。これらは GLSL 1.20 では不正な構造です。
ただし、それらを回避することはでき#define
ますが、これには手動での介入が少し必要です。#ifdef
をシェーダ ソース ファイルに挿入する必要があります。これを少し簡単にするためのシェーダー コンパイル トリックがあります。
実際、GL ES はまったく異なる一連の拡張機能を使用するため (一部はデスクトップ GL 拡張機能のミラーおよびサブセットですが)、これを実行することをお勧めします。
すべての GLSL シェーダー (デスクトップまたは ES) には「プリアンブル」が必要です。#version
シェーダーの最初のコメント以外のものは、宣言である必要があります。幸い、デスクトップ GL 2.1 と GL ES 2.0 のバージョンは同じです#version 1.20
。問題は次に来るものです:#extension
リスト (もしあれば)。これにより、シェーダーに必要な拡張機能が有効になります。
GL ES はデスクトップ GL とは異なる拡張子を使用するため、この拡張子リストを変更する必要があります。また、デスクトップ GL 2.1 拡張機能よりも多くの GLSL ES 拡張機能が必要になる可能性が高いため、これらのリストは 1:1 マッピングだけでなく、完全に異なるリストになります。
私の提案は、GLSL シェーダーに複数の文字列を与える機能を採用することです。つまり、実際のシェーダー ファイルにはプリアンブルが含まれていません。それらには実際の定義と機能しかありません。シェーダの本体。
GL ES で実行する場合、シェーダーの先頭に付加するグローバル プリアンブルがあります。デスクトップ GL には異なるグローバル プリアンブルがあります。コードは次のようになります。
GLuint shader = glCreateShader(/*shader type*/);
const char *shaderList[2];
shaderList[0] = GetGlobalPreambleString(); //Gets preamble for the right platform
shaderList[1] = LoadShaderFile(); //Get the actual shader file
glShaderSource(shader, 2, shaderList, NULL);
プリアンブルには、プラットフォーム固有の#define
. もちろんユーザー定義。そうすれば#ifdef
、さまざまなプラットフォーム用にコーディングできます。
両者には他にも違いがあります。たとえば、有効な ES 2.0 テクスチャ アップロード関数呼び出しはデスクトップ GL 2.1 で正常に動作しますが、必ずしも最適であるとは限りません。すべてのモバイル システムのように、ビッグ エンディアンのマシンで正常にアップロードされるものは、リトル エンディアンのデスクトップ マシンのドライバーから少しいじる必要があります。そのため、GL ES とデスクトップ GL で異なるピクセル転送パラメータを指定する方法が必要になる場合があります。
また、ES 2.0 とデスクトップ GL 2.1 には、利用したい拡張セットがいくつかあります。それらの多くは互いにミラーリングしようとしますが (OES_framebuffer_object は EXT_framebuffer_object のサブセットです)、上記のような「完全なサブセットではない」問題に遭遇する可能性があります。
私の謙虚な経験では、この種の要件に対する最善のアプローチは、追加のレイヤーを使用せずに純粋な C フレーバーでエンジンを開発することです。
私はPATRIA 3Dエンジンの主な開発者であり、ポータビリティに関してあなたが今言及した基本原則に基づいており、基本的な標準ライブラリでツールを開発するだけでこれを達成しました。
さまざまなプラットフォームでコードをコンパイルする労力は非常に最小限です。
ソリューション全体を移植するための実際の労力は、エンジンに組み込みたいコンポーネントに応じて計算できます。
例えば:
標準 C:
エンジン 3D
ゲームロジック
ゲームAI
物理
+
ウィンドウ インターフェイス (GLUT、EGL など) - プラットフォームによって異なりますが、デスクトップ用の GLUT とモバイル デバイス用の EGL が考えられます。
ヒューマン インターフェイス - 移植、Android 用の Java、IOS 用の OC、デスクトップのバージョンに依存します。
サウンドマネージャー - 移植に依存
市場サービス - 移植に依存
このようにして、作業の 95% をシームレスに再利用できます。
このソリューションをエンジンに採用しましたが、これまでのところ、初期投資の価値があります。