楽しみのために、Android用のシンプルなフラクタル表示アプリを作成しています。また、OpenGLを使用したことがないので、OpenGLを学ぶ機会としても使用しています。NeHeチュートリアルのAndroidポートを出発点として使用して、私のアプローチは、フラクタルを作成するためのすべての計算を行う1つのクラス(FractalModel)と、すべてのレンダリングを行うFractalViewを持つことです。
私が抱えている問題は、レンダリングを機能させることです。基本的に、各ポイントが1ピクセルに対応するさまざまな色のポイントのグラフをプロットしているので、画面全体に1x1の長方形をレンダリングし、寸法を使用してオフセットを計算し、1が存在するようにすることでこれを処理すると思いました。長方形と物理ピクセル間の1:1の対応。各ピクセルの色は個別に計算されるため、同じレンダリングコードを再利用して、フラクタルのさまざまな部分をレンダリングできます(後でパンとズームを追加したい)。
これが私が書いたビュークラスです:
public class FractalView extends GLSurfaceView implements Renderer {
private float[] mVertices;
private FloatBuffer[][] mVBuffer;
private ByteBuffer[][] mBuffer;
private int mScreenWidth;
private int mScreenHeight;
private float mXOffset;
private float mYOffset;
private int mNumPixels;
//references to current vertex coordinates
private float xTL;
private float yTL;
private float xBL;
private float yBL;
private float xBR;
private float yBR;
private float xTR;
private float yTR;
public FractalView(Context context, int w, int h){
super(context);
setEGLContextClientVersion(1);
mScreenWidth = w;
mScreenHeight = h;
mNumPixels = mScreenWidth * mScreenHeight;
mXOffset = (float)1.0/mScreenWidth;
mYOffset = (float)1.0/mScreenHeight;
mVertices = new float[12];
mVBuffer = new FloatBuffer[mScreenHeight][mScreenWidth];
mBuffer = new ByteBuffer[mScreenHeight][mScreenWidth];
}
public void onDrawFrame(GL10 gl){
int i,j;
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
mapVertices();
gl.glColor4f(0.0f,1.0f, 0.0f,.5f);
for(i = 0; i < mScreenHeight; i++){
for(j = 0; j < mScreenWidth; j++){
gl.glFrontFace(GL10.GL_CW);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVBuffer[i][j]);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, mVertices.length / 3);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
}
}
public void onSurfaceChanged(GL10 gl, int w, int h){
if(h == 0) { //Prevent A Divide By Zero By
h = 1; //Making Height Equal One
}
gl.glViewport(0, 0, w, h); //Reset The Current Viewport
gl.glMatrixMode(GL10.GL_PROJECTION); //Select The Projection Matrix
gl.glLoadIdentity(); //Reset The Projection Matrix
//Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(gl, 45.0f, (float)w / (float)h, 0.1f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW); //Select The Modelview Matrix
gl.glLoadIdentity();
}
public void onSurfaceCreated(GL10 gl, EGLConfig config){
gl.glShadeModel(GL10.GL_SMOOTH); //Enable Smooth Shading
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //Black Background
gl.glClearDepthf(1.0f); //Depth Buffer Setup
gl.glEnable(GL10.GL_DEPTH_TEST); //Enables Depth Testing
gl.glDepthFunc(GL10.GL_LEQUAL); //The Type Of Depth Testing To Do
//Really Nice Perspective Calculations
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
}
private void mapVertices(){
int i,j;
xTL = -1;
yTL = 1;
xTR = -1 + mXOffset;
yTR = 1;
xBL = -1;
yBL = 1 - mYOffset;
xBR = -1 + mXOffset;
yBR = 1 - mYOffset;
for(i = 0; i < mScreenHeight; i++){
for (j = 0; j < mScreenWidth; j++){
//assign coords to vertex array
mVertices[0] = xBL;
mVertices[1] = yBL;
mVertices[2] = 0f;
mVertices[3] = xBR;
mVertices[4] = xBR;
mVertices[5] = 0f;
mVertices[6] = xTL;
mVertices[7] = yTL;
mVertices[8] = 0f;
mVertices[9] = xTR;
mVertices[10] = yTR;
mVertices[11] = 0f;
//add doubleBuffer
mBuffer[i][j] = ByteBuffer.allocateDirect(mVertices.length * 4);
mBuffer[i][j].order(ByteOrder.nativeOrder());
mVBuffer[i][j] = mBuffer[i][j].asFloatBuffer();
mVBuffer[i][j].put(mVertices);
mVBuffer[i][j].position(0);
//transform right
transformRight();
}
//transform down
transformDown();
//reset x
xTL = -1;
xTR = -1 + mXOffset;
xBL = -1;
xBR = -1 + mXOffset;
}
}
//transform all the coordinates 1 "pixel" to the right
private void transformRight(){
xTL = xTL + mXOffset; //TL
xBL = xBL + mXOffset; //BL
xBR = xBR + mXOffset; //BR
xTR = xTR + mXOffset; //TR;
}
//transform all of the coordinates 1 pixel down;
private void transformDown(){
yTL = yTL - mYOffset;
yBL = yBL - mYOffset;
yBR = yBR - mYOffset;
yTR = yTR - mYOffset;
}
}
基本的に、これと同じ方法(レッスン2の正方形)で実行しようとしていますが、オブジェクトがはるかに多くなっています。1と-1は画面の端にほぼ対応していると思います(これが完全に正しいわけではないことはわかっていますが、投影行列の使用方法がよくわからないため、適切なリソースがない限り、これをできるだけ単純に保ちたいと思います。そこから学ぶことができます)が、OpenGLの座標は実際の画面座標とは別のものであることを理解しています。コードを実行すると、黒い画面(緑色になっているはずです)が表示されますが、LogCatはガベージコレクターが機能していることを示しているので、何かがわかります起こっている。何かが正しく行われなかったことが原因のバグなのか、それとも本当に遅いのかはわかりません。どちらの場合でも、私は別の方法で何をすべきですか?私はこれについてすべて間違っているのではないかと感じています。私は周りを見回しましたが、チュートリアルと例のほとんどは上記のリンクに基づいています。
編集:画面全体を埋めるテクスチャを生成してそれを描画するだけでこれを実行できることはわかっていますが、私が読んだリンクでは、フレームごとにテクスチャを再描画する必要がないため、処理が遅くなると書かれていました。とはいえ、パースペクティブが変更されたときにテクスチャを再描画するだけでよいので、これを考慮してコードを記述できます。私が現在抱えている主な問題は、ビットマップを描画し、正しく表示することです。