投影矩阵 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)
下面通过试验来加深对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;
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