2

これまでに達成できたことは次のとおりです。

  • GLSurfaceView/Renderer を初期化する
  • 画面に三角形を描く
  • 画面に正方形/長方形をレンダリングする
  • 画面にビットマップ テクスチャを追加する
  • レンダリング時に PNG の透過性が尊重されるようにする
  • 三角形を自動的にスケーリングして、すべての画面サイズで正しく表示されるようにします

ただし、スケーリングされた三角形を修正した後、背景の四角形 (テクスチャ付き) が画面いっぱいにならなくなりました。

背景が画面いっぱいにならなくなった

私はしばらくこれに固執しており、タオルを投げたところまで完全に困惑しています。

私が確信していない主な部分は、glFrustumf() と gluLookAt() の使用です。

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
    gl.glViewport(0, 0, width, height);

    ratio = (float) width / height;
    gl.glMatrixMode(GL10.GL_PROJECTION);        // set matrix to projection mode
    gl.glLoadIdentity();                        // reset the matrix to its default state
    gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);  // apply the projection matrix
}

@Override
public void onDrawFrame(GL10 gl) {
    // Clear the screen
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

    // Set GL_MODELVIEW transformation mode
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity(); // reset the matrix to its default state

    // When using GL_MODELVIEW, you must set the camera view
    GLU.gluLookAt(gl, 0, 0, -5f, 0f, 0f, 0f, 0.0f, 1.0f, 0.0f);

    bg.draw(gl);
    // ...
}

問題を確認する時間があれば、ファイルをhttps://bitbucket.org/koonkii/test_opengl/srcにアップロードしたので、コピーして貼り付けてコードを再作成する必要はありません。

4

2 に答える 2

4
GLU.gluLookAt(gl, 0, 0, -5f, 0f, 0f, 0f, 0.0f, 1.0f, 0.0f);

-5f を 0 に変更してみてください。ここで言っているのは、カメラを 5 単位後方に移動することです。したがって、正射影を行っていない限り (そうではないと思いますが、これをチェックしてみてください)、OpenGL が行っていることは次のとおりです。透視図に従って背景ポリゴンをスケーリングすると、「小さく」表示されます。

正射影を行うと、カメラを z 軸でどれだけ動かしても、常に同じサイズで表示されます。これは 2D OpenGL ベースのゲームに役立つので、上記のリンクを確認してください。

編集: gluPerspective と glOrtho

gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);

gluPerspective には「fovy」というパラメーターがあり、これは基本的に「Y 軸の視野」です。視野は、カメラが見ることのできる空間の量を表し、基本的にはその前にある頂点を「拡大」または「縮小」します。典型的な人間の目は 45º の FOV を持っています。

zNear と zFar は、ニア フラスタムとファー フラスタムの制限を表します。フラスタムは、表示領域の外側にある頂点を決定する目に見えない「ボックス」です。

アスペクトは、カメラの幅と高さの比率を決定します。

glOrtho は、FOV が常に 0 であるという意味で、gluPerspective の特殊なケースです。

gl.glOrthof(0.0f, (float) width, (float) height, 0.0f, 1.0f, -1.0f);

最初の 4 つのパラメータはクリッピング プレーンのサイズ (通常は画面のサイズ) を指定し、他の 2 つの値は錐台の近くと遠くを指定します (オブジェクトを「遠くに」配置して非表示にする場合を除き、これは必要ありません)。 .

これで少しはすっきりしたと思います。

于 2012-07-21T17:35:01.700 に答える
3

よし、ぐっすり眠り、正射影に関する RedOrav のアドバイスを適用した後、さらにブラウジングして動作させました!

RedOrav によって提供されたコード スニペットは実際に機能しましたが、正射影に切り替えた後も、幅が 0.15f という小さな正方形と三角形を描画していました。幅が 1 ピクセル未満なのでほとんど見えません。

背景/正方形/三角形のコードをより合理的なもの (30.0f) に変更した後、それらが表示されました!

コードをもう少しいじって、ポジショニングが適切に機能するようにしました。プロジェクトの作業コピーをチェックアウトしたい人のために、コードをbitbucketに送信しました。

G.getYPos() が必要な理由は、下の座標 = 0、上が画面の高さだからです。すべてのテクスチャを上下逆にすることなく、より良い反転方法を見つけることができませんでした。

重要な初期化部分は次のとおりです。

グローバルヘルパー

public class G {
    public static float ratio;
    public static int width, height;

    /** The texture pointer */
    public static int[] textures = new int[3];

    final static int TEXTURE_DEFAULT = 0;
    final static int TEXTURE_BG = 1;
    final static int TEXTURE_ANDROID = 2;
    final static int TEXTURE_TURTLE = 3;

    /**
     * Since (bottom = 0, top = height), we need to invert the values so they make sense logically.
     */
    public static int getYPos(int top) {
        return G.height - top;
    }
}

レンダラー クラス

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    this.loadGLTextures(gl);

    gl.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);    //Red Background
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
    gl.glViewport(0, 0, width, height);


    // Save these for global use.
    G.width = width;
    G.height = height;
    G.ratio = (float) width / height;


    // Set up orthogonal viewport and make adjustments for screen ratio
    gl.glViewport(0, 0, width, height);
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    GLU.gluOrtho2D(gl, 0, width, 0, height); // The parameters are weird but bottom = 0 so we need an inverter function G.

    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();


    // Start setting up the constructs we need
    bg = new Background();

    squares = new ArrayList<Square>();
    squares.add(new Square(width / 2, G.getYPos(0))); // middle/top of the screen
    squares.add(new Square(width / 2, G.height /2)); // center of the screen

    triangles = new ArrayList<Triangle>();
    triangles.add(new Triangle(0, G.getYPos(0))); // top left
    triangles.add(new Triangle(width, G.getYPos(height))); // bottom right
    triangles.add(new Triangle(width /2, height /2)); // middle
}

@Override
public void onDrawFrame(GL10 gl) {
    // Clear the screen
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

    bg.draw(gl);

    for (Square s : squares) {
        s.draw(gl);
    }

    // Draw correctly scaled triangles
    for (Triangle t : triangles) {
        t.draw(gl);
    }

    try {
        Thread.sleep(400);
    }
    catch (InterruptedException e) {
    }
}


/**
 * Loads the textures up.
 */
public void loadGLTextures(GL10 gl) {
    int[] texture_map = new int[] { R.drawable.bg_game, R.drawable.ic_launcher };
    Bitmap bitmap;

    // generate one texture pointer, keep 0 as blank/default
    gl.glGenTextures(texture_map.length, G.textures, 0);

    for (int i = 0; i < texture_map.length; i++) {
        // loading texture
        bitmap = BitmapFactory.decodeResource(context.getResources(), texture_map[i]);

        // ...and bind it to our array
        gl.glBindTexture(GL10.GL_TEXTURE_2D, G.textures[i +1]);

        // 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);

        // Use 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();
    }
}

背景クラス p

ublic class Background {
    private FloatBuffer vertexBuffer;   // buffer holding the vertices
    private float vertices[] = {
            -1.0f, -1.0f,  0.0f,        // V1 - bottom left
            -1.0f,  1.0f,  0.0f,        // V2 - top left
            1.0f, -1.0f,  0.0f,        // V3 - bottom right
            1.0f,  1.0f,  0.0f         // V4 - top right
    };

    private FloatBuffer textureBuffer;  // buffer holding the texture coordinates
    private float texture[] = {
            // Mapping coordinates for the vertices
            0.0f, 1.0f,     // top left     (V2)
            0.0f, 0.0f,     // bottom left  (V1)
            1.0f, 1.0f,     // top right    (V4)
            1.0f, 0.0f      // bottom right (V3)
    };


    public Background() {
        // Recalculate the vertices so they fit the screen
        vertices[0] = 0;        // v1 left
        vertices[1] = G.height; // v1 bottom

        vertices[3] = 0;        // v2 left
        vertices[4] = 0;        // v2 top

        vertices[6] = G.width;  // v3 right
        vertices[7] = G.height; // v3 bottom

        vertices[9] = G.width;  // v4 right
        vertices[10] = 0;       // v4 top


        // a float has 4 bytes so we allocate for each coordinate 4 bytes
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());

        // allocates the memory from the byte buffer
        vertexBuffer = byteBuffer.asFloatBuffer();

        // fill the vertexBuffer with the vertices
        vertexBuffer.put(vertices);

        // set the cursor position to the beginning of the buffer
        vertexBuffer.position(0);


        byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        textureBuffer = byteBuffer.asFloatBuffer();
        textureBuffer.put(texture);
        textureBuffer.position(0);
    }


    public void draw(GL10 gl) {
        gl.glEnable(GL10.GL_TEXTURE_2D); // Twig;

        // Bind the previously generated texture
        gl.glBindTexture(GL10.GL_TEXTURE_2D, G.textures[G.TEXTURE_BG]);

        // Point to our buffers
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        // Point to our vertex buffer
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

        // Draw the vertices as triangle strip
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);

        //Disable the client state before leaving
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        gl.glDisable(GL10.GL_TEXTURE_2D); // twig;
    }
}

Square クラス 位置があり、アルファ透明度を適用する点を除いて、background と非常によく似ています。

public class Square {
    private FloatBuffer vertexBuffer;   // buffer holding the vertices
    private float vertices[] = {
            -1.0f, -1.0f,  0.0f,        // V1 - bottom left
            -1.0f,  1.0f,  0.0f,        // V2 - top left
            1.0f, -1.0f,  0.0f,        // V3 - bottom right
            1.0f,  1.0f,  0.0f         // V4 - top right
    };

    private FloatBuffer textureBuffer;  // buffer holding the texture coordinates
    private float texture[] = {
            // Mapping coordinates for the vertices
            0.0f, 1.0f,     // top left     (V2)
            0.0f, 0.0f,     // bottom left  (V1)
            1.0f, 1.0f,     // top right    (V4)
            1.0f, 0.0f      // bottom right (V3)
    };


    public Square(float posX, float posY) {
        float w = 30f;
        float h = w;

        vertices[0] = posX - w; // left
        vertices[3] = posX - w;
        vertices[6] = posX + w; // right
        vertices[9] = posX + w;

        vertices[1] = posY - h; // top
        vertices[4] = posY + h;
        vertices[7] = posY - h; // bottom
        vertices[10] = posY + h;

        // a float has 4 bytes so we allocate for each coordinate 4 bytes
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());

        // allocates the memory from the byte buffer
        vertexBuffer = byteBuffer.asFloatBuffer();

        // fill the vertexBuffer with the vertices
        vertexBuffer.put(vertices);

        // set the cursor position to the beginning of the buffer
        vertexBuffer.position(0);



        byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        textureBuffer = byteBuffer.asFloatBuffer();
        textureBuffer.put(texture);
        textureBuffer.position(0);
    }


    /** The draw method for the square with the GL context */
    public void draw(GL10 gl) {
        // Enable alpha transparency
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);

        // bind the previously generated texture
        gl.glEnable(GL10.GL_TEXTURE_2D); // Twig;

        gl.glBindTexture(GL10.GL_TEXTURE_2D, G.textures[G.TEXTURE_ANDROID]);

        // Point to our buffers
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        // reset the colour for the square
        gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

        // Point to our vertex buffer
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

        // Draw the vertices as triangle strip
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);

        //Disable the client state before leaving
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        // Disable alpha transparency
        gl.glDisable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ZERO);

        gl.glDisable(GL10.GL_TEXTURE_2D); // twig;
    }
}

三角クラス

public class Triangle {
    private FloatBuffer vertexBuffer;   // buffer holding the vertices

    private float vertices[] = {
            -0.5f, -0.5f,  0.0f,        // V1 - first vertex (x,y,z)
             0.5f, -0.5f,  0.0f,        // V2 - second vertex
             0.0f,  0.5f,  0.0f         // V3 - third vertex
    };

    public Triangle(float posX, float posY) {
        int w = 30;
        int h = w;

        vertices[0] = posX - (w/2); // left
        vertices[3] = posX + (w/2); // right
        vertices[6] = posX;         // middle

        vertices[1] = posY - (h/2); // bottom
        vertices[4] = posY - (h/2); // bottom
        vertices[7] = posY + (h/2); // top

        // a float has 4 bytes so we allocate for each coordinate 4 bytes
        ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
        vertexByteBuffer.order(ByteOrder.nativeOrder());

        // allocates the memory from the byte buffer
        vertexBuffer = vertexByteBuffer.asFloatBuffer();

        // fill the vertexBuffer with the vertices
        vertexBuffer.put(vertices);

        // set the cursor position to the beginning of the buffer
        vertexBuffer.position(0);
    }

    public void draw(GL10 gl) {
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        // set the colour for the triangle
        gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

        // Point to our vertex buffer
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

        // Draw the vertices as triangle strip
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);

        // Reset the colour
        gl.glColor4f(1.0f, 1.0f, 1.0f, 0.0f);

        //Disable the client state before leaving
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    }
}

これが、OpenGL の開始に関して同様の問題を抱えている他の人に役立つことを願っています。

于 2012-07-22T05:19:02.793 に答える