Android openGL ES2.0 Matrix.frustumM和Matrix.setLookAtM参数详解

先看一段代码,对于学习OpenGL的童鞋来说,下面这段代码还算熟悉,但是可能不知道其中的参数的含义,下面针对这些参数进行说明讲解:

 @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        //计算宽高比
        float ratio=(float)width/height;
        //设置透视投影
        Matrix.frustumM(mProjectMatrix, 0, -ratio, ratio, -1, 1, 3, 20);
        //设置相机位置
        Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 10.0f, 0f, 0f, 0f, 1.0f, 1.0f, 0.0f);
        //计算变换矩阵
        Matrix.multiplyMM(mMVPMatrix,0,mProjectMatrix,0,mViewMatrix,0);
    }

学习这两个方法需要先了解openGL的3D坐标系,可以自行百度

Matrix.setLookAtM
需要填充的参数
float cx, //相机位置x
float cy, /相机位置y
float cz, //相机位置z
float tx, //相机目标点x
float ty, //相机目标点y
float tz, //相机目标点z
float upx, //相机UP向量X分量
float upy, //相机UP向量Y分量
float upz //相机UP向量Z分量

这个方法看起来很抽象,设几组参数对比一下效果,相机目标点,即绘制的3D图像,tx,ty, tz,为图像的中心位置设置到原点即 tx = 0,ty = 0, tz = 0; 相机的位置,即观察者眼睛的位置, 我们设置在目标点的正前方(位置z轴正方向),cx = 0, cy = 0, cz = 10; 接着是摄像机顶部的方向了

例如设置up方向为y轴正方向,upx = 0,upy = 1,upz = 0。这是相机正对着目标图像,则绘制出来的效果相当于我们在Y轴方向看目标。代码如下:

 Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5.0f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

如果设置up方向为x轴正方向,upx = 1,upy = 0,upz = 0,绘制的图像就会相当于我们在X轴方向看目标
代码如下:

 Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5.0f, 0f, 0f, 0f, 1.0f, 0f, 0.0f);

如果设置up方向为x轴正方向,upx = 1,upy = 1,upz = 0,绘制的图像就会相当于我们在X轴与Y轴的分割线方向看目标,代码如下:

 Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5.0f, 0f, 0f, 0f, 1.0f, 1.0f, 0.0f);

注意:如果设置在z轴方向,图像就会看不见。Matrix.setLookAtM,的作用大体就是这样。

Matrix.frustumM
需要填充的参数有
float left, //near面的left
float right, //near面的right
float bottom, //near面的bottom
float top, //near面的top
float near, //near面距离
float far //far面距离
设置这些参数能起到的作用:先是left,right和bottom,top,这4个参数会影响图像左右和上下缩放比,所以往往会设置的值分别-(float) width / height和(float) width / height,top和bottom和top会影响上下缩放比,如果left和right已经设置好缩放,则bottom只需要设置为-1,top设置为1,这样就能保持图像不变形。也可以将left,right 与bottom,top交换比例,即bottom和top设置为 -height/width 和 height/width, left和right设置为-1和1。
near和far参数稍抽象一点,就是一个立方体的前面和后面,near和far需要结合拍摄相机即观察者眼睛的位置来设置,例如setLookAtM中设置cx = 0, cy = 0, cz = 10,near设置的范围需要是小于10才可以看得到绘制的图像,如果大于10,图像就会处于了观察这眼睛的后面,这样绘制的图像就会消失在镜头前,far参数,far参数影响的是立体图形的背面,far一定比near大,一般会设置得比较大,如果设置的比较小,一旦3D图形尺寸很大,这时候由于far太小,这个投影矩阵没法容纳图形全部的背面,这样3D图形的背面会有部分隐藏掉的。

以上是 Matrix.frustumM和Matrix.setLookAtM参数详解,可能同学会问 Matrix.multiplyMM(mMVPMatrix,0,mProjectMatrix,0,mViewMatrix,0);这个函数的参数说明,这个等下次再进行讲解。
附上完整代码,绘制一个正三角形,供大家参考学习,可直接运行:

/**
 * Description:
 */
public class TriangleWithCamera extends Shape {

    private FloatBuffer vertexBuffer;
    private final String vertexShaderCode =
            "attribute vec4 vPosition;" +
                    "uniform mat4 vMatrix;"+
                    "void main() {" +
                    "  gl_Position = vMatrix*vPosition;" +
                    "}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";

    private int mProgram;

    static final int COORDS_PER_VERTEX = 3;
    static float triangleCoords[] = {
            0.5f,  0.5f, 0.0f, // top
            -0.5f, -0.5f, 0.0f, // bottom left
            0.5f, -0.5f, 0.0f  // bottom right
    };

    private int mPositionHandle;
    private int mColorHandle;

    private float[] mViewMatrix=new float[16];
    private float[] mProjectMatrix=new float[16];
    private float[] mMVPMatrix=new float[16];

    //顶点个数
    private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
    //顶点之间的偏移量
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 每个顶点四个字节

    private int mMatrixHandler;

    //设置颜色,依次为红绿蓝和透明通道
    float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };

    public TriangleWithCamera(View mView) {
        super(mView);
        ByteBuffer bb = ByteBuffer.allocateDirect(
                triangleCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());

        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(triangleCoords);
        vertexBuffer.position(0);
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
                vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
                fragmentShaderCode);

        //创建一个空的OpenGLES程序
        mProgram = GLES20.glCreateProgram();
        //将顶点着色器加入到程序
        GLES20.glAttachShader(mProgram, vertexShader);
        //将片元着色器加入到程序中
        GLES20.glAttachShader(mProgram, fragmentShader);
        //连接到着色器程序
        GLES20.glLinkProgram(mProgram);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        //计算宽高比
        float ratio=(float)width/height;
        //设置透视投影
        Matrix.frustumM(mProjectMatrix, 0, -ratio, ratio, -1, 1, 3, 20);
        //设置相机位置
        Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5.0f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
        //计算变换矩阵
        Matrix.multiplyMM(mMVPMatrix,0,mProjectMatrix,0,mViewMatrix,0);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        //将程序加入到OpenGLES2.0环境
        GLES20.glUseProgram(mProgram);
        //获取变换矩阵vMatrix成员句柄
        mMatrixHandler= GLES20.glGetUniformLocation(mProgram,"vMatrix");
        //指定vMatrix的值
        GLES20.glUniformMatrix4fv(mMatrixHandler,1,false,mMVPMatrix,0);
        //获取顶点着色器的vPosition成员句柄
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
        //启用三角形顶点的句柄
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        //准备三角形的坐标数据
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                vertexStride, vertexBuffer);
        //获取片元着色器的vColor成员的句柄
        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
        //设置绘制三角形的颜色
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);
        //绘制三角形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
        //禁止顶点数组的句柄
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }

}
public abstract class Shape implements GLSurfaceView.Renderer {

    protected View mView;

    public Shape(View mView){
        this.mView=mView;
    }

    public int loadShader(int type, String shaderCode){
        //根据type创建顶点着色器或者片元着色器
        int shader = GLES20.glCreateShader(type);
        //将资源加入到着色器中,并编译
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);
        return shader;
    }

}

刚开始学习OpenGL,有什么描述错误的地方请指正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值