Androidのあ〜ん
Android開発のための狭くて浅い自分用メモ
Latest Entries
SDK1.6+NDKr4
NDKソースコード
Javaソースコード
その5にテクスチャの複数読み込み&テクスチャ切り替えを加えただけですが
複数テクスチャ読み込み
テクスチャ切り替え描画
速度差は以下の通り。表示はJava/NDKの順
エミュレータ:2.06/2.82

HT-03A:3.54/13.70

かなり高速になったようです
Droid:12.35/25.00

今度は差が出ました
テクスチャ変更のオーバーヘッドが結構キツイってことですかねぇ?
NDKソースコード
Javaソースコード
その5にテクスチャの複数読み込み&テクスチャ切り替えを加えただけですが
複数テクスチャ読み込み
// テクスチャ読み込み(実際にはダミーを用意)
void loadTexture( void ){
// テクスチャロードが面倒なんで捏造
int i,j;
for( i=0 ; i<64 ; i++ ){
for( j=0 ; j<64 ; j++ ){
if( i < 32 ){
texBuff0[ i ][ j ][ 0 ] = 0xff; // R
texBuff0[ i ][ j ][ 1 ] = 0x00; // G
texBuff0[ i ][ j ][ 2 ] = 0x00; // B
texBuff0[ i ][ j ][ 3 ] = 0xff; // A
texBuff1[ i ][ j ][ 0 ] = 0x00; // R
texBuff1[ i ][ j ][ 1 ] = 0xff; // G
texBuff1[ i ][ j ][ 2 ] = 0x00; // B
texBuff1[ i ][ j ][ 3 ] = 0xff; // A
} else {
texBuff0[ i ][ j ][ 0 ] = 0x00; // R
texBuff0[ i ][ j ][ 1 ] = 0x00; // G
texBuff0[ i ][ j ][ 2 ] = 0xff; // B
texBuff0[ i ][ j ][ 3 ] = 0xff; // A
texBuff1[ i ][ j ][ 0 ] = 0xff; // R
texBuff1[ i ][ j ][ 1 ] = 0xff; // G
texBuff1[ i ][ j ][ 2 ] = 0x00; // B
texBuff1[ i ][ j ][ 3 ] = 0xff; // A
}
}
}
int textures[2];
glGenTextures( 2, textures );
textures0 = textures[0];
glBindTexture( GL_TEXTURE_2D, textures0 );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); // 縮小するときピクセルの中心に最も近いテクスチャ要素で補完
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); // 拡大するときピクセルの中心付近の線形で補完
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); // s座標の1を超える端処理をループにしない
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); // t座標の1を超える端処理をループにしない
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); // テクスチャとモデルの合成方法の指定(この場合置き換え)
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, texBuff0 );
textures1 = textures[1];
glBindTexture( GL_TEXTURE_2D, textures1 );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); // 縮小するときピクセルの中心に最も近いテクスチャ要素で補完
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); // 拡大するときピクセルの中心付近の線形で補完
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); // s座標の1を超える端処理をループにしない
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); // t座標の1を超える端処理をループにしない
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); // テクスチャとモデルの合成方法の指定(この場合置き換え)
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, texBuff1 );
}
テクスチャ切り替え描画
void drawTriangle( int num ){
// LOGI( "X,Y = %d,%d", x, y );
int i;
glEnable( GL_TEXTURE_2D ); // テクスチャを使う
glBlendFunc( GL_ONE, GL_ZERO ); // アルファブレンドを殺す
glActiveTexture( GL_TEXTURE0 );
for( i=0 ; i<drawNum ; i++ ){
if( textureType[i] == 0 ){
glBindTexture( GL_TEXTURE_2D, textures0 );
} else {
glBindTexture( GL_TEXTURE_2D, textures1 );
}
glVertexPointer( 2, GL_FIXED, 0, &vertex[i*6] ); // 表示座標のセット
glTexCoordPointer( 2, GL_FLOAT, 0, &triangleTexture[i*6] );
glDrawArrays( GL_TRIANGLES, 0, 3 );
}
}
速度差は以下の通り。表示はJava/NDKの順
エミュレータ:2.06/2.82

HT-03A:3.54/13.70

かなり高速になったようです
Droid:12.35/25.00

今度は差が出ました
テクスチャ変更のオーバーヘッドが結構キツイってことですかねぇ?
SDK1.6+NDKr4
ソースコード
デバッグ付Java版
NDKr4bが出てますがまだ試してません。BugFixぐらいらしいのでまぁそのうち…
NDK OpenGLのテクスチャですがヘッダファイルの「PixelFormat」や「OES_read_format」みてもさっぱりわからんので
ベタに8bitRGBA(GL_RGBA)にしてます。「GL_RGB」の場合は基本5,6,5を2byteにビットシフトで生成するようです
つまりどういうことかというと「テクスチャフォーマットの変換APIなんて用意シテネーヨ」ってことです
めんどいので64x64の上下を色分けしたものを変わりに使ってます
検索した限りではオープンライセンスのC++変換クラスが公開されているようですが…
「glTexImage2D」でフォーマット指定してます
http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml
ヘッダを見る限りESでは上のほとんどを実装していないようですが、カラーパレットってどうやるんだ???
描画部分はJava版とあまり変わらず。テクスチャ座標が「GL_FIXED」→「GL_FLOAT」になってますが
速度差は以下の通り。表示はJava/NDKの順
テクスチャの種類が違うので単純比較はダメな気もしますがキニシナイ
エミュレータ:2.89/3.68

HT-03A:13.51/24.39

Droid:29.41/27.78

NDKが負けてる…
ソースコード
デバッグ付Java版
NDKr4bが出てますがまだ試してません。BugFixぐらいらしいのでまぁそのうち…
NDK OpenGLのテクスチャですがヘッダファイルの「PixelFormat」や「OES_read_format」みてもさっぱりわからんので
ベタに8bitRGBA(GL_RGBA)にしてます。「GL_RGB」の場合は基本5,6,5を2byteにビットシフトで生成するようです
つまりどういうことかというと「テクスチャフォーマットの変換APIなんて用意シテネーヨ」ってことです
めんどいので64x64の上下を色分けしたものを変わりに使ってます
検索した限りではオープンライセンスのC++変換クラスが公開されているようですが…
// テクスチャ読み込み
void loadTexture( void ){
// テクスチャロードが面倒なんで捏造
int i,j;
for( i=0 ; i<64 ; i++ ){
for( j=0 ; j<64 ; j++ ){
if( i < 32 ){
texBuff[ i ][ j ][ 0 ] = 0xff; // R
texBuff[ i ][ j ][ 1 ] = 0x00; // G
texBuff[ i ][ j ][ 2 ] = 0x00; // B
texBuff[ i ][ j ][ 3 ] = 0xff; // A
} else {
texBuff[ i ][ j ][ 0 ] = 0x00; // R
texBuff[ i ][ j ][ 1 ] = 0x00; // G
texBuff[ i ][ j ][ 2 ] = 0xff; // B
texBuff[ i ][ j ][ 3 ] = 0xff; // A
}
}
}
glGenTextures( 1, &textures );
glBindTexture( GL_TEXTURE_2D, textures );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); // 縮小するときピクセルの中心に最も近いテクスチャ要素で補完
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); // 拡大するときピクセルの中心付近の線形で補完
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); // s座標の1を超える端処理をループにしない
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); // t座標の1を超える端処理をループにしない
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); // テクスチャとモデルの合成方法の指定(この場合置き換え)
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, texBuff );
// glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_SHORT, texBuff );
}
「glTexImage2D」でフォーマット指定してます
http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml
ヘッダを見る限りESでは上のほとんどを実装していないようですが、カラーパレットってどうやるんだ???
// 三角描画
void drawTriangle( int num ){
// LOGI( "X,Y = %d,%d", x, y );
glEnable( GL_TEXTURE_2D ); // テクスチャを使う
glBlendFunc( GL_ONE, GL_ZERO ); // アルファブレンドを殺す
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, textures );
// glDisable( GL_TEXTURE_2D ); // テクスチャを使わない
glVertexPointer( 2, GL_FIXED, 0, vertex ); // 表示座標のセット
glColorPointer( 4, GL_UNSIGNED_BYTE, 0, colors ); // カラーのセット
glTexCoordPointer( 2, GL_FLOAT, 0, triangleTexture );
// glTexCoordPointer( 2, GL_FIXED, 0, triangleTexture );
glDrawArrays( GL_TRIANGLES, 0, num*3 ); // 登録数*3だけ描画する
}
描画部分はJava版とあまり変わらず。テクスチャ座標が「GL_FIXED」→「GL_FLOAT」になってますが
速度差は以下の通り。表示はJava/NDKの順
テクスチャの種類が違うので単純比較はダメな気もしますがキニシナイ
エミュレータ:2.89/3.68

HT-03A:13.51/24.39

Droid:29.41/27.78

NDKが負けてる…
ソースコード
デバッグ付Java版
三角形です。αチャンネルを半分にして半透明重ね合わせをしてます
描画のとこだけ切り出し
Java版と変わりません。
今回半透明にしていますが、不透明にする場合は「glDrawArrays」の前に「glDisable( GL_BLEND )」してください
今まで書いてませんでしたが、デバッグ出力で半透明にしているため描画時にブレンディングを止める必要があります
エミュレータ:8.93/16.95

HT-03A:14.08/38.46

Droid:34.48/45.45

Droidが他ほど差が無いのは画面解像度の差ですかね?
デバッグ付Java版
三角形です。αチャンネルを半分にして半透明重ね合わせをしてます
GLfixed vertex[drawNum*2*3];
unsigned char colors[drawNum*4*3];
// 描画
void Java_test_sample_TSNdkOpenGL04_TSNdkOpenGL04_ndkOpenGLDraw( JNIEnv* env )
{
// LOGI( "ndkOpenGLDraw" );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // 描画バッファクリア&背景塗りつぶし
// 射影行列の指定
glDisable( GL_TEXTURE_2D ); // テクスチャは使わない
int x = 0;
int y = 0;
int i = 0, j = 0;
int size = 1;
for( i=0 ; i<drawNum ; i++ ){
if( drawWidth != 0 ){
x = rand() % drawWidth;
}
if( drawHeight != 0 ){
y = rand() % drawHeight;
}
size = ( rand() % 10 )*2 + 4;
// size = 10;
setTriangle( x*ONE, y*ONE, size*ONE, i );
for( j=0 ; j<4*3 ; j++ ){
if( ( j % 4 ) == 3 ){
colors[i*4*3 + j] = 0x80;
} else {
colors[i*4*2 + j] = 0xff;
}
}
}
drawTriangle( drawNum );
}
// 三角登録
void setTriangle( int x, int y, int size, int num ){
vertex[num*6] = x;
vertex[num*6+1] = y;
vertex[num*6+2] = x - size/2;
vertex[num*6+3] = y - size;
vertex[num*6+4] = x + size/2;
vertex[num*6+5] = y - size;
}
// 三角描画
void drawTriangle( int num ){
// LOGI( "X,Y = %d,%d", x, y );
glVertexPointer( 2, GL_FIXED, 0, vertex ); // 表示座標のセット
glColorPointer( 4, GL_UNSIGNED_BYTE, 0, colors ); // カラーのセット
glDrawArrays( GL_TRIANGLES, 0, num*3 ); // 登録数*3だけ描画する
}
描画のとこだけ切り出し
Java版と変わりません。
今回半透明にしていますが、不透明にする場合は「glDrawArrays」の前に「glDisable( GL_BLEND )」してください
今まで書いてませんでしたが、デバッグ出力で半透明にしているため描画時にブレンディングを止める必要があります
エミュレータ:8.93/16.95

HT-03A:14.08/38.46

Droid:34.48/45.45

Droidが他ほど差が無いのは画面解像度の差ですかね?
えーと原因というか、修正方法が判明しました
glOrthox → glOrthof
とすることでGL_FIXED系に対応することが判明しました…
というか、今までのコードがGL_FIXED使ってるのに0x10000を掛けてないの気づけよ>俺
glOrthoxで整数演算系にセットしてたのに表示物が固定小数点演算してたらダメに決まってますよねぇ…
OpenGLはそういった記述が特にナシに混ぜこぜに動いちゃってる環境もあるようなので
(つーか他のサンプルでふつーに動いてるのを試してるだけだし…って言い訳がましいか)
なんだよそれ…って感じですが「Androidはダメなのよ〜」と覚えておくことにします
/GLES/gl.h見ても
/* Available only in Common profile */はfloatで、int他は拡張扱いでした
基本は浮動小数点系を使うのが正しい模様
ついでにcolorテーブルは「GL_UNSIGNED_BYTE」でunsigned charで指定に変更です
RGBA4byteでこっちのがわかりやすいし
その2 その2a その3 は修正済です
glOrthox → glOrthof
とすることでGL_FIXED系に対応することが判明しました…
というか、今までのコードがGL_FIXED使ってるのに0x10000を掛けてないの気づけよ>俺
glOrthoxで整数演算系にセットしてたのに表示物が固定小数点演算してたらダメに決まってますよねぇ…
OpenGLはそういった記述が特にナシに混ぜこぜに動いちゃってる環境もあるようなので
(つーか他のサンプルでふつーに動いてるのを試してるだけだし…って言い訳がましいか)
なんだよそれ…って感じですが「Androidはダメなのよ〜」と覚えておくことにします
/GLES/gl.h見ても
/* Available only in Common profile */はfloatで、int他は拡張扱いでした
基本は浮動小数点系を使うのが正しい模様
ついでにcolorテーブルは「GL_UNSIGNED_BYTE」でunsigned charで指定に変更です
RGBA4byteでこっちのがわかりやすいし
その2 その2a その3 は修正済です
http://togetter.com/li/32751
ソースコード
何番煎じかわからないけどやってみたので上げてみました
最初は試しに「View.getDrawingCache()」で重ね合わせたViewの画像を取り込む実験をしてみましたが、
SurfaceViewの画像はGPUのビデオエリアにあるってことらしくて、このやりかたはOUT
ここで3時間ぐらい潰して金曜は終了
(TS_Eva.javaに残骸があります)
んでBitmap+Canvasに直して約2時間かけてそれっぽいものはできあがり
5時間とわやっぱりヘボだな>俺
めんどくさいので画像サイズをあわせるとかやってません

…………さぁ突っ込め!
ソースコード
何番煎じかわからないけどやってみたので上げてみました
最初は試しに「View.getDrawingCache()」で重ね合わせたViewの画像を取り込む実験をしてみましたが、
SurfaceViewの画像はGPUのビデオエリアにあるってことらしくて、このやりかたはOUT
ここで3時間ぐらい潰して金曜は終了
(TS_Eva.javaに残骸があります)
んでBitmap+Canvasに直して約2時間かけてそれっぽいものはできあがり
5時間とわやっぱりヘボだな>俺
めんどくさいので画像サイズをあわせるとかやってません

…………さぁ突っ込め!


