RenderScript には Compute 用と Graphics 用の 2種類あります。
前回のサンプルは Compute 用です。
下記のように root 関数の宣言が異なります。
Compute : void root( const T* input, T* output ) Graphics: int root()
・Compute
ForEach 命令によりデータの数だけ root() が呼ばれる。
Shader のような実行方法。
・Graphics
RSSurfaceView を使い bindRootScript() で登録すると毎フレーム
root() が呼ばれる。
1フレーム分の描画セットアップコードを記述できる。
RenderScript にはいくつか組み込まれた描画命令があります。
内蔵の固定シェーダーを用いて描画を行なっているようです。
簡単に描画できる反面、大量に描画する用途には向いていません。
デバッグやテスト時には便利そうです。使ってみます。
特に何もしない Activity。SimpleView を呼び出しているだけ。
// SimpleActivity.java package jp.flatlib.ap02; import android.app.Activity; import android.os.Bundle; public class SimpleActivity extends Activity { private SimpleView mSimpleView= null; @Override public void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); mSimpleView= new SimpleView( this ); setContentView( mSimpleView ); } @Override protected void onPause() { super.onPause(); mSimpleView.pause(); } @Override protected void onResume() { super.onResume(); mSimpleView.resume(); } }
View では RSSurfaceView を使い renderloop.rs を bind します。
これで renderloop.rs の root() が呼ばれるようになります。
// SimpleView.java package jp.flatlib.ap02; import android.content.Context; import android.content.res.Resources; import android.renderscript.RSSurfaceView; import android.renderscript.RenderScriptGL; public class SimpleView extends RSSurfaceView { private RenderScriptGL mRS; private ScriptC_renderloop mScript; public SimpleView( Context context ) { super( context ); initRS(); } private void initRS() { if( mRS != null ){ return; } // RenderScriptGL を作る RenderScriptGL.SurfaceConfig sc= new RenderScriptGL.SurfaceConfig(); mRS= createRenderScriptGL( sc ); Resources res= getContext().getResources(); // renderloop.rs を登録する mScript= new ScriptC_renderloop( mRS, res, R.raw.renderloop ); mRS.bindRootScript( mScript ); } @Override public void onAttachedToWindow() { super.onAttachedToWindow(); initRS(); } @Override public void onDetachedFromWindow() { if( mRS != null ){ mRS= null; destroyRenderScriptGL(); } } }
Graphics 用 RenderScript では 1フレーム分の描画命令を記述します。
戻り値は描画の更新間隔です。msec
// renderloop.rs #pragma version(1) #pragma rs java_package_name(jp.flatlib.ap02) #include "rs_graphics.rsh" int root() { // 背景クリア rsgClearColor( 1.0f, 0.5f, 0.0f, 0.0f ); // 塗りつぶし四角形描画 rsgDrawRect( 100.0f, 200.0f, 150.0f, 250.0f, 0.0f ); // 文字列描画 rsgFontColor( 1.0f, 1.0f, 1.0f, 1.0f ); rsgDrawText( "RenderScript test", 50.0f, 50.0f ); return 33; // 30fps }
任意メッシュを使った描画、GLSL シェーダーの利用、RenderScript による
動的な頂点生成を行うにはもう少し複雑な初期化手順が必要となります。
その前に RenderScript のメモリについて整理します。
● Allocation
Allocation は RenderScript が扱うメモリ確保します。
Java のメモリを直接触ることは出来ず、転送には専用の命令が必要です。
(1) Java Heap Java (2) Native Heap RenderScript (3) GPU Resource GPU
Allocation は (2)/(3) の両方を管理します。
Allocation で確保したメモリは RenderScript でアクセスでき、
GPU Resource としてマップすることが可能です。
任意のタイミングで HW への転送や同期が行われます。
GPU ハードウエアリソースにマップする場合は確保時に USAGE フラグで
用途を指定します。
この指定方法は Direct3D API に非常によく似ています。名称も。
Allocation.USAGE_GRAPHICS_CONSTANTS Uniform Allocation.USAGE_GRAPHICS_RENDER_TARGET (Android 4.0 API Lv14 以上で対応) Allocation.USAGE_GRAPHICS_TEXTURE Texture Allocation.USAGE_GRAPHICS_VERTEX Buffer (Vertex/Index) Allocation.USAGE_SCRIPT Script
(1) から (2)/(3) への転送は容易ですが逆方向は簡単ではありません。
● Element と Type
Shader 等 GPU がアクセスするリソースのフォーマットを指定します。
Element 頂点フォーマット、ピクセルフォーマット等 Type Element の配列。Uniform や Texture の構造を定義
Element は構造体の定義です。
データ型とメンバ変数名の組み合わせでできています。
例えば RGBA8888 256×26 の 2D テクスチャは、I8_4 の Basic Element が
256×256 の 2次元に並んだ構造として Type で表現できます。
● Element/Type Reflection
render.rs の中で、下記のように構造体として頂点フォーマットを定義すると
自動的に class ScriptFiled_VertexType が作られます。
// render.rs typedef struct VertexType { float3 position; float3 normal; float2 texcoord; } VertexType_t; VertexType_t* VertexType_n; // unuse
(VertexType_n はダミーです。何らかの参照がないと class が作られないため。)
この場合の Element のイメージは↓こんな感じ。
Element: F32_3 "position" F32_3 "normal" F32_2 "texcoord"
ScriptFiled_VertexType の中では構造に従った Element や Type が生成される
ので、これを使って GPU 用のメモリを Allocation することができます。
ScriptFiled_VertexType vtype= new ScriptFiled_VertexType( rs, 100 ); Element element= vtype.getElement(); // Element の参照 Allocation vbuffer= Allocation.createTyped( rs, vtype.getType(), Allocation.USAGE_GRAPHICS_VERTEX ); // Type を使った確保
ScriptFiled_VertexType は中で Allocation を作ってくれるので↓これで OK
ScriptFiled_VertexType vtype= new ScriptFiled_VertexType( rs, 100, Allocation.USAGE_GRAPHICS_VERTEX ); Allocation vbuffer= vtype.getAllocation();
続きます 「Android 3.x RenderScript (3) 独自シェーダーの割り当てとメッシュの描画(2D)」
関連エントリ
・Android 3.x RenderScript (1)