Coin163

首页 > Android OpenGL透视投影

Android OpenGL透视投影

相关标签: android opengl

2020腾讯云双十一活动,全年最低!!!(领取3500元代金券),
地址https://cloud.tencent.com/act/cps/redirect?redirect=1074

【阿里云】双十一活动,全年抄底价,限时3天!(老用户也有),
入口地址https://www.aliyun.com/1111/home

相关推荐:Android OpenGL ES 学习计划

    大家好,我将在后续时间学习Android OpenGL ES 相关知识,这是我第一次写博客,写的不好,请大家多多指正。     参考教材《Addison.Wesley.OpenGL.ES.2.0.Programming.Guide.Aug.2008.pdf》    Android 系统源码中与OpenGL ES 相关的部分

Android OpenGL透视投影

首先申明下,本文为笔者学习《OpenGL ES应用开发实践指南》的笔记,并加入笔者自己的理解和归纳总结。

1、透视除法

OpenGL会把每个gl_Position的x、y和z分量都除以它的w分量。当w分量用来表示距离的时候,会使得较远处的物体被移动到距离渲染区域中心更近的地方。

添加w分量创建三维图
private static final int POSITION_COMPONENT_COUNT = 4;

float[] tableVerticesWithTriangles = {
	// 中心点
	0f, 0f, 0f, 1.5f, 1f, 1f, 1f,

	// 四个角
	-0.5f, -0.8f, 0f, 1f, 0.7f, 0.7f, 0.7f,
	 0.5f, -0.8f, 0f, 1f, 0.7f, 0.7f, 0.7f,
	 0.5f,  0.8f, 0f, 2f, 0.7f, 0.7f, 0.7f,
	-0.5f,  0.8f, 0f, 2f, 0.7f, 0.7f, 0.7f,
	-0.5f, -0.8f, 0f, 1f, 0.7f, 0.7f, 0.7f,

	// 直线
	-0.5f, 0f, 0f, 1.5f, 1f, 0f, 0f,
	 0.5f, 0f, 0f, 1.5f, 1f, 0f, 0f,

	// 点
	0f, -0.25f, 0f, 1.25f, 0, 0, 1,
	0f,  0.25f, 0f, 1.75f, 1, 0, 0
};
显示如下

2、视椎体

相关推荐:一道Android OpenGL笔试题

题目 设计一个Android平台的Gallery组件,要求Gallery中每个item内的图片显示达成有效显示的最大精度,并保证Gallery在滚屏时能够全60FPS帧率地及时显示出加载的图片。请详细说明实现架构、关键技术点及APIs。 约束条件:GPU空间传输通道带宽较小,对于400*40

视椎体是一个立方体,其远端比近端大,从而使其变成一个被截断的金字塔。视椎体有一个焦点,当你用透视投影观察一个场景时,那个场景看上去就像你的头被放在了焦点处。焦点和视椎体小端的距离被称为焦距。


3、定义透视投影

Matrix的orthoM方法可以生成一个透视投影
perspectiveM(float[] m, int offset,
          float fovy, float aspect, float near, float far)
  • float[] m:目标数组,存储正交投影矩阵
  • int mOffset:结果矩阵起始的偏移量
  • float fovy:视眼角度
  • float aspect:屏幕的宽高比,等于宽度/高度
  • float near:到近处平面的距离,必须是正值。
  • float far:到远处平面的距离,必须是正值且大于到近处平面距离。
投影矩阵,a代表焦距
a = 1.0f / Math.tan((fovy * Math.PI / 180.0f) / 2.0f)

4、绘制着色器

(1) 使用投影矩阵
Matrix.perspectiveM(projectionMatrix, 0, 45, (float)width / (float)height, 1, 10);
(2) 在z轴上移动物体,先定义一个modelMatrix模型
Matrix.setIdentityM(modelMatrix, 0);
Matrix.translateM(modelMatrix, 0, 0, 0, -2.8f);
(3) 利用模型移动物体
float[] temp = new float[16];
Matrix.multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0);
System.arraycopy(temp, 0, projectionMatrix, 0, temp.length);
(4) OpenGLPerspectiveShaderRender类
在onSurfaceChanged方法,定义透视矩阵,并使用模型矩阵把数据显示出来。
private class OpenGLPerspectiveShaderRender implements GLSurfaceView.Renderer {
	private final static String A_POSITION = "a_Position";
	private final static String A_COLOR = "a_Color";
	private final static String U_MATRIX = "u_Matrix";

			private static final int POSITION_COMPONENT_COUNT = 2;
	private static final int COLOR_COMPONENT_COUNT = 3;
	private static final int BYTES_PER_FLOAT = 4;
	private static final int STRIDE = (POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT)
			* BYTES_PER_FLOAT;

	private float[] projectionMatrix = new float[16];
	private float[] modelMatrix = new float[16];
	private FloatBuffer vertexData;
	private int mProgramId;
	private int aPositionLocation, aColorLocation, uMatrixLocation;

	OpenGLPerspectiveShaderRender() {
		float[] tableVerticesWithTriangles = {
				// 中心点
				0f, 0f, 1f, 1f, 1f,

				// 四个角
				-0.5f, -0.8f, 0.7f, 0.7f, 0.7f,
				 0.5f, -0.8f, 0.7f, 0.7f, 0.7f,
				 0.5f,  0.8f, 0.7f, 0.7f, 0.7f,
				-0.5f,  0.8f, 0.7f, 0.7f, 0.7f,
				-0.5f, -0.8f, 0.7f, 0.7f, 0.7f,

				// 直线
				-0.5f, 0f, 1f, 0f, 0f,
				0.5f, 0f, 1f, 0f, 0f,

				// 点
				0f, -0.25f, 0, 0, 1,
				0f,  0.25f, 1, 0, 0
		};

		vertexData = ByteBuffer
				.allocateDirect(tableVerticesWithTriangles.length * BYTES_PER_FLOAT)
				.order(ByteOrder.nativeOrder())
				.asFloatBuffer();
		vertexData.put(tableVerticesWithTriangles);
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

		mProgramId = useProgram(R.raw.ortho_vertex_shader, R.raw.ortho_fragment_shader);

		// 获取Attribute位置
		aPositionLocation = GLES20.glGetAttribLocation(mProgramId, A_POSITION);
		aColorLocation = GLES20.glGetAttribLocation(mProgramId, A_COLOR);
		uMatrixLocation = GLES20.glGetUniformLocation(mProgramId, U_MATRIX);

		vertexData.position(0);
		GLES20.glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT,
				GLES20.GL_FLOAT, false, STRIDE, vertexData);
		GLES20.glEnableVertexAttribArray(aPositionLocation);

		vertexData.position(POSITION_COMPONENT_COUNT);
		GLES20.glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT,
				GLES20.GL_FLOAT, false, STRIDE, vertexData);
		GLES20.glEnableVertexAttribArray(aColorLocation);
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		GLES20.glViewport(0, 0, width, height);

		// 创建透视投影
		Matrix.perspectiveM(projectionMatrix, 0, 45, (float)width / (float)height, 1, 10);

		// 定义模型矩阵
		Matrix.setIdentityM(modelMatrix, 0);
		// z轴平移-2.8
		Matrix.translateM(modelMatrix, 0, 0, 0, -2.8f);

		// 把投影矩阵和模型矩阵相乘
		float[] temp = new float[16];
		Matrix.multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0);
		System.arraycopy(temp, 0, projectionMatrix, 0, temp.length);
	}

	@Override
	public void onDrawFrame(GL10 gl) {
		GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

		// 给着色器传递正交投影矩阵
		GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, projectionMatrix, 0);

		// 绘制三角形
		GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 6);

		// 绘制直线
		GLES20.glDrawArrays(GLES20.GL_LINES, 6, 2);

		// 绘制点
		GLES20.glDrawArrays(GLES20.GL_POINTS, 8, 1);

		// 绘制点
		GLES20.glDrawArrays(GLES20.GL_POINTS, 9, 1);
	}

}
显示如下

5、增加旋转

旋转矩阵,绕x轴、y轴和z轴旋转所用矩阵的定义

在modelMatrix进行平移以后,对模型进行旋转操作
Matrix.rotateM(modelMatrix, 0, -60, 1f, 0f, 0f);
显示如下

原文

Android OpenGL透视投影 首先申明下,本文为笔者学习《OpenGL ES应用开发实践指南》的笔记,并加入笔者自己的理解和归纳总结。 1、透视除法 OpenGL会把每个gl_Position的x、y和z分量都除以它的w

------分隔线----------------------------