現在、Androidプラットフォーム用の小さなOpenGLゲームを開発していますが、レンダリングされたフレームの上にテキストをレンダリングする簡単な方法(プレーヤーのスコアを備えたHUDなど)があるのでしょうか。テキストには、カスタムフォントも使用する必要があります。
オーバーレイとしてビューを使用する例を見てきましたが、後で他のプラットフォームにゲームを移植する可能性があるため、それを行うかどうかはわかりません。
何か案は?
Android SDKには、OpenGLビューにテキストを描画する簡単な方法がありません。次のオプションがあります。
テクスチャへのテキストのレンダリングは、スプライトテキストデモの外観よりも簡単です。基本的な考え方は、Canvasクラスを使用してビットマップにレンダリングし、ビットマップをOpenGLテクスチャに渡すことです。
// Create an empty, mutable bitmap
Bitmap bitmap = Bitmap.createBitmap(256, 256, Bitmap.Config.ARGB_4444);
// get a canvas to Paint over the bitmap
Canvas canvas = new Canvas(bitmap);
bitmap.eraseColor(0);
// get a background image from resources
// note the image format must match the bitmap format
Drawable background = context.getResources().getDrawable(R.drawable.background);
background.setBounds(0, 0, 256, 256);
background.draw(canvas); // draw the background to our bitmap
// Draw the text
Paint textPaint = new Paint();
textPaint.setTextSize(32);
textPaint.setAntiAlias(true);
textPaint.setARGB(0xff, 0x00, 0x00, 0x00);
// draw the text centered
canvas.drawText("Hello World", 16,112, textPaint);
//Generate one texture pointer...
gl.glGenTextures(1, textures, 0);
//...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
//Create Nearest Filtered Texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
//Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_Edge
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
//Use the Android GLUtils to specify a two-dimensional texture image from our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
//Clean up
bitmap.recycle();
JVitela によって投稿された答えを展開する tutorial を書きました。基本的には同じ考え方を使用しますが、各文字列をテクスチャにレンダリングする代わりに、フォントファイルのすべての文字をテクスチャにレンダリングし、それを使用して、さらに減速することなくフルダイナミックテキストレンダリングを可能にします(初期化が完了すると) 。
さまざまなフォントアトラスジェネレーターと比較して、私の方法の主な利点は、フォントのバリエーションやサイズごとに大きなビットマップを出荷する代わりに、プロジェクトに小さなフォントファイル(.ttf .otf)を出荷できることです。フォントファイルのみを使用して、任意の解像度で完璧な品質のフォントを生成できます。
tutorial には、すべてのプロジェクトで使用できる完全なコードが含まれています:)
このリンクによると:
http://code.neenbedankt.com/how-to-render-an-Android-view-to-a-bitmap
任意のビューをビットマップにレンダリングできます。おそらく、必要に応じてビュー(テキスト、画像などを含む)をレイアウトし、それをビットマップにレンダリングできると想定する価値があります。
JVitelaのコード 上記 を使用すると、そのビットマップをOpenGLテクスチャとして使用できるはずです。
CBFGと、ロード/レンダリングコードのAndroidポートを見てください。コードをプロジェクトにドロップして、すぐに使用できるはずです。
CBFG- http://www.codehead.co.uk/cbfg
Androidローダー- http://www.codehead.co.uk/cbfg/TexFont.Java
Spriteテキストの例を見て、そのようなタスクでは非常に複雑に見えます。テクスチャへのレンダリングも検討しましたが、パフォーマンスヒットが発生する可能性が心配です。代わりにビューを表示する必要があり、その橋を渡るときの移植を心配する必要があります:)
GLSurfaceViewサンプル の「Sprite Text」サンプルを見てください。
私見では、ゲームでOpenGL ESを使用する3つの理由があります:
ゲームのデザインでは、テキストを描くことは常に問題です。なぜなら、物を描くので、ウィジェットなどを使用して、一般的なアクティビティのルックアンドフィールを持つことができないからです。
フレームワークを使用して、TrueTypeフォントからビットマップフォントを生成し、レンダリングできます。私が見たすべてのフレームワークは同じように動作します:描画時にテキストの頂点とテクスチャー座標を生成します。これはOpenGLの最も効率的な使用方法ではありません。
最良の方法は、コードの早い段階で頂点とテクスチャにリモートバッファー(頂点バッファーオブジェクト-VBO)を割り当て、描画時の遅延メモリ転送操作を回避することです。
ゲームプレイヤーはテキストを読むことを好まないので、長く動的に生成されたテキストを書かないことに注意してください。ラベルには、静的テクスチャを使用して、時間とスコアに動的テキストを残すことができます。両方とも数文字の数値です。
だから、私の解決策は簡単です:
リモートの静的バッファを使用する場合、描画操作は高速です。
画面の位置(画面の対角線の割合に基づく)とテクスチャ(静的および文字)を使用してXMLファイルを作成し、レンダリングする前にこのXMLをロードします。
高いFPSレートを得るには、描画時にVBOを生成しないでください。
GLの使用を主張する場合、テキストをテクスチャにレンダリングできます。ほとんどのHUDが比較的静的であると仮定すると、テクスチャをテクスチャメモリに頻繁にロードする必要はありません。
ロード/レンダリングコードのCBFG
およびAndroidポートを見てください。コードをプロジェクトにドロップして、すぐに使用できるはずです。
この実装には問題があります。フォントのビットマップのサイズを変更しようとすると、1文字しか表示されません(特殊文字が必要です)描画全体が失敗します:(
私はこれを数時間探していましたが、これは私が出会った最初の記事であり、最良の答えがありますが、最も人気のある答えは見当違いです。確かに私が必要なもの。 weichselとshakazedの答えはボタン上では正しかったが、記事では少々あいまいだった。プロジェクトにあなたを正しく配置します。ここ:既存のサンプルに基づいて新しいAndroidプロジェクトを作成するだけです。 ApiDemosを選択します。
ソースフォルダの下を見てください
ApiDemos/src/com/example/Android/apis/graphics/spritetext
そして、必要なものはすべて見つかります。
static textの場合:
長いテキストの場合、時々更新する必要があります:
a number(フォーマット00.0):
OnDrawイベントでは、シェーダーに送信される値変数のみを更新します。
precision highp float;
precision highp sampler2D;
uniform float uTime;
uniform float uValue;
uniform vec3 iResolution;
varying vec4 v_Color;
varying vec2 vTextureCoord;
uniform sampler2D s_texture;
void main() {
vec4 fragColor = vec4(1.0, 0.5, 0.2, 0.5);
vec2 uv = vTextureCoord;
float devisor = 10.75;
float digit;
float i;
float uCol;
float uRow;
if (uv.y < 0.45) {
if (uv.x > 0.75) {
digit = floor(uValue*10.0);
digit = digit - floor(digit/10.0)*10.0;
i = 48.0 - 32.0 + digit;
uRow = floor(i / 10.0);
uCol = i - 10.0 * uRow;
fragColor = texture2D( s_texture, uv / devisor * 2.0 + vec2((uCol-1.5) / devisor, uRow / devisor) );
} else if (uv.x > 0.5) {
uCol = 4.0;
uRow = 1.0;
fragColor = texture2D( s_texture, uv / devisor * 2.0 + vec2((uCol-1.0) / devisor, uRow / devisor) );
} else if (uv.x > 0.25) {
digit = floor(uValue);
digit = digit - floor(digit/10.0)*10.0;
i = 48.0 - 32.0 + digit;
uRow = floor(i / 10.0);
uCol = i - 10.0 * uRow;
fragColor = texture2D( s_texture, uv / devisor * 2.0 + vec2((uCol-0.5) / devisor, uRow / devisor) );
} else if (uValue >= 10.0) {
digit = floor(uValue/10.0);
digit = digit - floor(digit/10.0)*10.0;
i = 48.0 - 32.0 + digit;
uRow = floor(i / 10.0);
uCol = i - 10.0 * uRow;
fragColor = texture2D( s_texture, uv / devisor * 2.0 + vec2((uCol-0.0) / devisor, uRow / devisor) );
} else {
fragColor = vec4(0.0, 0.0, 0.0, 0.0);
}
} else {
fragColor = vec4(0.0, 0.0, 0.0, 0.0);
}
gl_FragColor = fragColor;
}
上記のコードは、フォントアトラス(テクスチャ)の2行目の7列目で0から始まるテクスチャアトラスで機能します。
https://www.shadertoy.com/view/Xl23Dw を参照してください(ただし、テクスチャが間違っています)