android / openGL:用方块填充2d视口

时间:2012-07-21 17:13:38

标签: android opengl-es orthogonal

到目前为止,我所取得的成就是:

  • 初始化GLSurfaceView / Renderer
  • 在屏幕上绘制一个三角形
  • 在屏幕上呈现正方形/矩形
  • 向屏幕添加位图纹理
  • 确保渲染时符合PNG透明度
  • 自动缩放三角形,使其正确显示所有屏幕尺寸

然而,在固定缩放三角形后,背景矩形(带纹理)不再填满屏幕。

The background no longer fills up the screen

我现在已经坚持了一段时间,并且对于我已经抛弃的那一点感到非常困惑。

我不确定的主要部分是使用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,因此您无需通过复制粘贴重新创建代码。

2 个答案:

答案 0 :(得分:3)

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

尝试将-5f更改为0,你在这里所说的是将相机移回5个单位,因此除非你正在进行正交投影(我认为你不是,所以试试看{{3} })OpenGL正在做的是根据你的透视视图缩放你的背景多边形,你会看到它“更小”。

如果进行正交投影,无论您在z轴上移动相机多少,都会看到它的大小相同。这对于基于2D OpenGL的游戏很有用,所以请查看上面的链接。

编辑:gluPerspective和glOrtho

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

gluPerspective有一个名为'fovy'的参数,它基本上是'Y轴中的视野'。视野表示相机可以看到的空间量,基本上是“扩展”或“收缩”在它之前发生的任何顶点。典型的人眼有45º视野。

zNear和zFar表示近视和远视平截头体的限制,视锥体是一个看不见的“盒子”,它确定哪些顶点在观察区域之外。

Aspect确定相机宽度和高度之间的比率。

glOrtho是gluPerspective的特例,因为FOV总是为0。

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

前四个参数指定剪裁平面的大小(通常是屏幕的大小),另外两个值指定近视和远视的平截头体(除非你想通过放置它们来隐藏对象,否则你不需要它们)很远'。

我希望这能为你清理一下。

答案 1 :(得分: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 class 非常类似于背景,除了它有一个位置并应用alpha透明度。

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时遇到类似问题。