OpenGL中原点的位置

时间:2014-01-22 16:13:30

标签: android opengl-es

我开始使用Android中的OpenGL ES,我遇到了一个我不太了解的情况。 OpenGL的原点应该是屏幕的左下角,对吗?因为对我来说,它似乎在屏幕的中间。到目前为止,我只是通过翻译和旋转到我想要的坐标系来解决它,但我想先了解为什么会发生这种情况。下面,这是一个将精灵放在屏幕死点的最小例子。我没有在此代码中执行任何翻译或轮换。

package com.lyrismobilestudio.opengltest;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.os.Bundle;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.ByteOrder;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.EGLConfig;

public class MainActivity extends Activity {
    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        GLSurfaceView view = new GLSurfaceView(this);
        Renderer renderer = new MyRenderer(this);
        view.setRenderer(renderer);
        setContentView(view);
    }
}

class MyRenderer implements Renderer {
    public Sprite strike;
    public Context context;

    public MyRenderer(Context context) {
        this.context = context;
        strike = new Sprite();
    }

    @Override public void onDrawFrame(GL10 gl) {
        gl.glClearColor(.5f,.5f,1f,0f);
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        strike.draw(gl);
        try { Thread.sleep(100); } catch (Exception e) {}
    }

    @Override public void onSurfaceChanged(GL10 gl, int width, int height){
    }

    @Override public void onSurfaceCreated(GL10 gl, EGLConfig arg1) {
        strike.loadTexture(gl, R.drawable.strike, context);
    }
}

class Sprite {
    FloatBuffer vertexBuffer;
    FloatBuffer textureBuffer;
    ByteBuffer indexBuffer;
    private int[] textures = new int[1];

    public Sprite() {
        float[] vertices = {
            -.1f,  .1f,
            .1f,  .1f,
            .1f, -.1f,
            -.1f, -.1f,
        };
        float[] textureVertices = new float[]{
            0f, 0f,
            1f, 0f,
            1f, 1f,
            0f, 1f
        };
        byte indices[] = {
            0, 1, 2,
            0, 2, 3
        };
        ByteBuffer temp = ByteBuffer.allocateDirect(vertices.length*4);
        temp.order(ByteOrder.nativeOrder());
        vertexBuffer = temp.asFloatBuffer();
        vertexBuffer.put(vertices);
        vertexBuffer.position(0);
        temp = ByteBuffer.allocateDirect(textureVertices.length*4);
        temp.order(ByteOrder.nativeOrder());
        textureBuffer = temp.asFloatBuffer();
        textureBuffer.put(textureVertices);
        textureBuffer.position(0);
        indexBuffer = ByteBuffer.allocateDirect(indices.length);
        indexBuffer.put(indices);
        indexBuffer.position(0);
    }

    public void draw(GL10 gl){
        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE_MINUS_SRC_ALPHA);
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_BYTE, indexBuffer);
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    }

    public void loadTexture(GL10 gl, int texture, Context context){
        InputStream imageStream = context.getResources().openRawResource(texture);
        Bitmap bitmap = null;
        try {
            bitmap = BitmapFactory.decodeStream(imageStream);
        } catch (Exception e) {
        } finally {
            try {  
                imageStream.close();
                imageStream=null;
            } catch (Exception e) {
            }
        }
        gl.glGenTextures(1, textures, 0);
        gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[0]);
        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);
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();
    }
}

2 个答案:

答案 0 :(得分:0)

原点位于屏幕中央。 X指向右,Y指向上方,Z指向屏幕外。由于您没有更改投影矩阵,因此它在每个方向上从-1变为1.

答案 1 :(得分:0)

默认情况下,OpenGL在屏幕上使用一个视口,覆盖x轴和y轴的坐标范围-1到+1。因此原点位于屏幕的中心。请注意,因为x和y的坐标范围相同,所以您的对象将显示为拉伸(除非您的屏幕是正方形...)。可以在这里找到一个很好的例子:http://developer.android.com/guide/topics/graphics/opengl.html

为了满足屏幕的几何形状(以及查看在-1 / + 1范围之外绘制的对象),您需要引入投影矩阵。然后你还需要一个相机变换矩阵,它定义了你在坐标空间中的位置以及方向。