我开始使用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();
}
}
答案 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范围之外绘制的对象),您需要引入投影矩阵。然后你还需要一个相机变换矩阵,它定义了你在坐标空间中的位置以及方向。