5-OpenGLES绘制棱锥&深度测试&表面剔除

三角形
    triangles:三角形集
    triangle_strip:三角形带(用的最多)
    triangle_fan:扇面

顶点着色模式:
    1.smooth:平滑模式(渐变过渡)。默认。
    2.flat:单调(跟最后一个点的颜色相同)。

深度轴:z轴
深度缓冲区:每个像素的深度值。
深度测试:启用z值,被遮挡的物体看不见。

剔除:如果看不见的部分,告诉openGL不要绘图,提高性能。

public class MyActivity extends Activity {
	private MyRenderer render;
	private MyGLSurfaceView view;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		view = new MyGLSurfaceView(this);
		render = new MyRenderer();
		view.setRenderer(render);
		view.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);// 脏渲染,命令渲染
		setContentView(view);
	}

	class MyGLSurfaceView extends GLSurfaceView {
		public MyGLSurfaceView(Context context) {
			super(context);
		}

		public MyGLSurfaceView(Context context, AttributeSet attrs) {
			super(context, attrs);
		}
	}

	class MyRenderer implements GLSurfaceView.Renderer {
		private float ratio, xrotate, yrotate;

		@Override
		public void onSurfaceCreated(GL10 gl, EGLConfig config) {
			// 清屏色
			gl.glClearColor(0f, 0f, 0f, 1f);
			// 启用顶点缓冲区
			gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
			// 启用颜色缓冲区
			gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
		}

		@Override
		public void onSurfaceChanged(GL10 gl, int width, int height) {
			// 设置视口
			gl.glViewport(0, 0, width, height);
			ratio = (float) width / (float) height;
			// 投影矩阵
			gl.glMatrixMode(GL10.GL_PROJECTION);
			// 加载单位矩阵
			gl.glLoadIdentity();
			// 设置平截头体
			gl.glFrustumf(-ratio, ratio, -1, 1, 3f, 7f);
		}

		@Override
		public void onDrawFrame(GL10 gl) {
			// 清除颜色缓冲区和深度缓冲区
			gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
			// 设置绘图颜色
			gl.glColor4f(1f, 0f, 0f, 1f);

			// 启用深度测试;否则最后绘制底面的始终显示,不管是否被遮挡,总能看见!
			gl.glEnable(GL10.GL_DEPTH_TEST);

			// 启用表面剔除
			gl.glEnable(GL10.GL_CULL_FACE);
			// CCW:counter clock wise-->逆时针
			// CW:clock wise--> 顺时针
			gl.glFrontFace(GL10.GL_CCW);// 指定逆时针为正面(锥面是逆时针绘制的)
			// 剔除背面(圆锥体里面)
			gl.glCullFace(GL10.GL_BACK);

			// GL10.GL_SMOOTH:平滑着色(默认)
			// GL10.GL_FLAT:单调模式着色
			gl.glShadeModel(GL10.GL_FLAT);

			// 操作模型视图矩阵
			gl.glMatrixMode(GL10.GL_MODELVIEW);
			gl.glLoadIdentity();
			// 设置眼球的参数
			GLU.gluLookAt(gl, 0f, 0f, 5f, 0f, 0f, 0f, 0f, 1f, 0f);

			// 旋转角度
			gl.glRotatef(xrotate, 1, 0, 0);
			gl.glRotatef(yrotate, 0, 1, 0);

			// 计算点坐标
			float r = 0.5f;// 半径
			float x = 0f, y = 0f, z = -0.5f;

			/******************** 锥面 ************************/
			// 顶点坐标集合
			List<Float> coordsList = new ArrayList<Float>();
			// 添加锥顶点
			coordsList.add(0f);
			coordsList.add(0f);
			coordsList.add(0.5f);

			// 顶点颜色集合
			List<Float> colorList = new ArrayList<Float>();
			colorList.add(1f);// r
			colorList.add(0f);// g
			colorList.add(0f);// b
			colorList.add(1f);// a

			/******************** 锥底 ************************/
			// 锥底坐标
			List<Float> coordsConeBottomList = new ArrayList<Float>();
			coordsConeBottomList.add(0f);
			coordsConeBottomList.add(0f);
			coordsConeBottomList.add(-0.5f);

			boolean flag = false;
			// 底面
			for (float alpha = 0f; alpha < Math.PI * 6; alpha += (float) (Math.PI / 8)) {
				// 锥面
				x = (float) (r * Math.cos(alpha));
				y = (float) (r * Math.sin(alpha));
				coordsList.add(x);
				coordsList.add(y);
				coordsList.add(z);

				// 锥底坐标
				coordsConeBottomList.add(x);
				coordsConeBottomList.add(y);
				coordsConeBottomList.add(z);

				// 点颜色值
				if (flag = !flag) {
					// 黄色
					colorList.add(1f);
					colorList.add(1f);
					colorList.add(0f);
					colorList.add(1f);
				} else {
					// 红色
					colorList.add(1f);
					colorList.add(0f);
					colorList.add(0f);
					colorList.add(1f);
				}
			}
			// 在颜色缓冲区增加一个颜色
			if (flag = !flag) {
				// 黄色
				colorList.add(1f);
				colorList.add(1f);
				colorList.add(0f);
				colorList.add(1f);
			} else {
				// 红色
				colorList.add(1f);
				colorList.add(0f);
				colorList.add(0f);
				colorList.add(1f);
			}

			// 颜色缓冲区
			ByteBuffer colorBuffer = list2ByteBuffer(colorList);
			gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
			// 绘制锥面
			gl.glVertexPointer(3, GL10.GL_FLOAT, 0, list2ByteBuffer(coordsList));
			gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, coordsList.size() / 3);

			// 锥底也是逆时针绘制,是从锥体里面绘制的,所以要剔除正面,留背面(即外底表面可视表面)
			gl.glCullFace(GL10.GL_FRONT);
			// 绘制锥底
			colorBuffer.position(4 * 4);//单位:字节(字节缓冲区),定位到:4个分量×floatSize,即下一个颜色
			                            //如果是浮点缓冲区,则position()参数值为4.
			gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
			gl.glVertexPointer(3, GL10.GL_FLOAT, 0, list2ByteBuffer(coordsConeBottomList));
			gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, coordsConeBottomList.size() / 3);
		}
	}

	private ByteBuffer list2ByteBuffer(List<Float> list) {
		ByteBuffer ibb = ByteBuffer.allocateDirect(list.size() * 4);
		ibb.order(ByteOrder.nativeOrder());
		FloatBuffer fbb = ibb.asFloatBuffer();
		for (Float f : list) {
			fbb.put(f);
		}
		ibb.position(0);
		return ibb;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		float step = 5f;
		if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
			render.xrotate -= step;
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
			render.xrotate += step;
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
			render.yrotate += step;
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
			render.yrotate -= step;
		}
		// 请求渲染,和脏渲染配合使用
		view.requestRender();
		return super.onKeyDown(keyCode, event);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

itzyjr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值