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 轴上移动多少相机,您将始终看到相同的大小。这对于基于 OpenGL 的 2D 游戏很有用,因此请查看上面的链接。

编辑:gluPerspective 和 glOrtho

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

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

zNear 和 zFar 表示近和远视锥体限制,视锥体是一个不可见的“盒子”,它决定了哪些顶点在可视区域之外。

纵横比决定了相机的宽度和高度之间的比率。

glOrtho 是 gluPerspective 的一个特例,因为 FOV 始终为 0。

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

前四个参数指定剪切平面的大小(通常是屏幕的大小),其他两个值指定近和远的截锥体(除非您想通过将对象放置“远”来隐藏对象,否则不需要它们) .

我希望这对您有所帮助。

于 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 类 与背景非常相似,除了它有一个位置并应用 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 时遇到类似问题的人。

于 2012-07-22T05:19:02.793 回答