【OpenGL ES】投影矩阵 Projection学习理解

投影矩阵 Projection

 

在当前的手机画面显示中,把空间3d的物体显示到2d平面的屏幕上,需要进行投影处理。

(如果未来出现了空间立体显示器,则是另外一种处理)

 

关于投影,可参考

http://www.songho.ca/opengl/gl_projectionmatrix.html

 

对于透视投影,可以使用Matrix.frustumM方法来生成一个矩阵,用来对顶点进行操作。

 

void android.opengl.Matrix.frustumM(float[] m, int offset, float left, float right, float bottom, float top, float near, float far)

 

08-14 10:27:13.925 18563 18580 E AndroidRuntime: java.lang.ArrayIndexOutOfBounds

Exception: length=16; index=16

08-14 10:27:13.925 18563 18580 E AndroidRuntime:        at android.opengl.Matrix

.frustumM(Matrix.java:365)

08-14 10:27:13.925 18563 18580 E AndroidRuntime:        at com.example.atestopen

gl.TestRender.onSurfaceChanged(TestRender.java:491)

下面通过试验来加深对leftrightbottomtopnearfar几个参数的理解,看看它们是如何影响投影效果的。

 

    public void onSurfaceChanged(GL10 glUnused, int width, int height)

    {

        // Set the OpenGL viewport to the same size as the surface.

        GLES20.glViewport(0, 0, width, height);

        // Create a new perspective projection matrix. The height will stay the same

        // while the width will vary as per aspect ratio.

        final float ratio = (float) width / height;

        final float left = -ratio;

        final float right = ratio;

        final float bottom = -1.0f;//-1

        final float top = 1.0f;

        final float near = 1.0f;//1

        final float far = 9.0f;//10

     

        Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);

    }

初始效果

 

投影平移效果

    public void onSurfaceChanged(GL10 glUnused, int width, int height)

    {

        // Set the OpenGL viewport to the same size as the surface.

        GLES20.glViewport(0, 0, width, height);

        // Create a new perspective projection matrix. The height will stay the same

        // while the width will vary as per aspect ratio.

        final float ratio = (float) width / height;

        final float left = -ratio-0.5f;

        final float right = ratio-0.5f;

        final float bottom = -1.0f;//-1

        final float top = 1.0f;

        final float near = 1.0f;//1

        final float far = 9.0f;//10

        Log.d("gltest", "onSurfaceChanged called");

        Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);

    }

 

 

调整xy的比例,可以进行缩放

        final float ratio = (float) width / height;

        final float left = -ratio*3;

        final float right = ratio*3;

        final float bottom = -1.0f*3;//-1

        final float top = 1.0f*3;

        final float near = 1.0f;//1

        final float far = 9.0f;//10

        Log.d("gltest", "onSurfaceChanged called");

        Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);

    }   

 

水平方向上的压缩

        final float ratio = (float) width / height;

        final float left = -ratio*3;

        final float right = ratio*3;

        final float bottom = -1.0f;//-1

        final float top = 1.0f;

        final float near = 1.0f;//1

        final float far = 9.0f;//10

 

 

可以看出,投影的处理和投影仪的效果类似,可以调节画面的偏移,缩放

 

空间上的截断

        final float near = 1.0f;//1

        final float far = 4.0f;//10

 

 

OpenGL ES 中的投影矩阵可以使用透视投影和正交投影两种方式进行设置。 透视投影是一种模拟人眼观察物体的方式,近处的物体看起来比远处的物体大,而且在远处的物体看起来比在近处的物体更小。在 OpenGL ES 中,透视投影的矩阵通常由 glFrustum() 或者 gluPerspective() 函数生成。这些函数所需要的参数包括视角、画面宽高比、近裁剪面和远裁剪面的距离。 正交投影则是一种无论远近都能保持物体大小一致的投影方式。在 OpenGL ES 中,正交投影的矩阵通常由 glOrtho() 函数生成。这个函数需要指定可视空间的左、右、上、下、近、远六个面。 下面是一个简单的 OpenGL ES 代码示例,使用透视投影和正交投影来绘制一个立方体: ```c++ // 使用透视投影绘制立方体 glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1, 1, -1, 1, 1, 10); // 绘制立方体 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, 0, -5); glRotatef(angle, 1, 1, 1); glColor3f(1, 0, 0); glutWireCube(2); // 使用正交投影绘制立方体 glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-2, 2, -2, 2, 1, 10); // 绘制立方体 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, 0, -5); glRotatef(angle, 1, 1, 1); glColor3f(0, 0, 1); glutWireCube(2); ``` 其中,glFrustum() 函数生成的透视投影矩阵,可以让离观察者比较近的物体显得比较大,而离观察者比较远的物体显得比较小。glOrtho() 函数生成的正交投影矩阵,则可以让物体无论离观察者多远,都保持一致的大小。 需要注意的是,在使用不同的投影方式时,需要先将当前矩阵模式设置为投影矩阵模式,然后再进行矩阵的设置和变换。最后,需要将矩阵模式设置回模型视图矩阵模式,以便绘制物体。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值