By 何明桂(http://blog.csdn.net/hmg25) 转载请注明出处
通过之前文章–概念篇的学习,我们今天编写一个简单的入门程序,实现一个不断绕x轴,y轴旋转的彩色立方体,效果如下:
在Android中我们使用GLSurfaceView来显示OpenGL视图,GLSurfaceView:是其中很重要的一个类,此类位于 Android.opengl包下,用于管理是一块可以是复合视图机器人系统的内存的特殊的曲面。管理一个使表面呈现 OpenGL 的 EGL 显示。接受一个用户提供输入Render对象进行显示。从 UI 线程实现一个专用线程渲染界面实现3D性能。支持按需要和连续的呈现。 包装、 跟踪,和检查 OpenGL 渲染器调用的错误。所以首先我们需要创建一个GLSurfaceView。
<ul> <li class="alt"><span class="keyword">public</span> <span class="keyword">class</span> mainActivity <span class="keyword">extends</span> Activity {</li> <li class=""> CubeRenderer mCubeRenderer; <span class="comment">//我们自定义的立方体Renderer</span></li> <li class="alt"> <span class="annotation">@Override</span></li> <li class=""> <span class="keyword">public</span> <span class="keyword">void</span> onCreate(Bundle savedInstanceState) {</li> <li class="alt"> <span class="keyword">super</span>.onCreate(savedInstanceState);</li> <li class=""> requestWindowFeature(Window.FEATURE_NO_TITLE); <span class="comment">// 去掉标题</span></li> <li class="alt"> GLSurfaceView GLView = <span class="keyword">new</span> GLSurfaceView(<span class="keyword">this</span>); <span class="comment">//创建一个GLSurfaceView</span></li> <li class=""> mCubeRenderer = <span class="keyword">new</span> CubeRenderer();</li> <li class="alt"> GLView.setRenderer(mCubeRenderer);</li> <li class=""> setContentView(GLView);</li> <li class="alt"></li> <li class=""> }</li> <li class="alt">}</li> <li class="alt">
接下来我们的主要工作就是去创建一个继承Renderer接口的CubeRenderer。Renderer是一个专门用来渲染3D的接口。继承它,我们需要重载以下方法: public void onDrawFrame(GL10 gl)
{
//渲染的绘图操作,重绘时调用
}
public void onSurfaceChanged(GL10 gl, int width, int height)
{
//视窗改变时调用,通常在此设置视窗范围以及透视,投影范围
}
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
//创建时调用,通常在此进行初始化设置
}
以下是我们CubeRenderer的完整代码:
</li> <li class="alt"> <ol class="dp-j" start="1"> <li class="alt"><span class="keyword">public</span> <span class="keyword">class</span> CubeRenderer <span class="keyword">implements</span> Renderer {</li> <li class=""></li> <li class="alt"> <span class="keyword">float</span> box[] = <span class="keyword">new</span> <span class="keyword">float</span>[] {</li> <li class=""> <span class="comment">// FRONT</span></li> <li class="alt"> -<span class="number">0</span>.5f, -<span class="number">0</span>.5f, <span class="number">0</span>.5f,</li> <li class=""> <span class="number">0</span>.5f, -<span class="number">0</span>.5f, <span class="number">0</span>.5f,</li> <li class="alt"> -<span class="number">0</span>.5f, <span class="number">0</span>.5f, <span class="number">0</span>.5f,</li> <li class=""> <span class="number">0</span>.5f, <span class="number">0</span>.5f, <span class="number">0</span>.5f,</li> <li class="alt"> <span class="comment">// BACK</span></li> <li class=""> -<span class="number">0</span>.5f, -<span class="number">0</span>.5f, -<span class="number">0</span>.5f,</li> <li class="alt"> -<span class="number">0</span>.5f, <span class="number">0</span>.5f, -<span class="number">0</span>.5f,</li> <li class=""> <span class="number">0</span>.5f, -<span class="number">0</span>.5f, -<span class="number">0</span>.5f,</li> <li class="alt"> <span class="number">0</span>.5f, <span class="number">0</span>.5f, -<span class="number">0</span>.5f,</li> <li class=""> <span class="comment">// LEFT</span></li> <li class="alt"> -<span class="number">0</span>.5f, -<span class="number">0</span>.5f, <span class="number">0</span>.5f,</li> <li class=""> -<span class="number">0</span>.5f, <span class="number">0</span>.5f, <span class="number">0</span>.5f,</li> <li class="alt"> -<span class="number">0</span>.5f, -<span class="number">0</span>.5f, -<span class="number">0</span>.5f,</li> <li class=""> -<span class="number">0</span>.5f, <span class="number">0</span>.5f, -<span class="number">0</span>.5f,</li> <li class="alt"> <span class="comment">// RIGHT</span></li> <li class=""> <span class="number">0</span>.5f, -<span class="number">0</span>.5f, -<span class="number">0</span>.5f,</li> <li class="alt"> <span class="number">0</span>.5f, <span class="number">0</span>.5f, -<span class="number">0</span>.5f,</li> <li class=""> <span class="number">0</span>.5f, -<span class="number">0</span>.5f, <span class="number">0</span>.5f,</li> <li class="alt"> <span class="number">0</span>.5f, <span class="number">0</span>.5f, <span class="number">0</span>.5f,</li> <li class=""> <span class="comment">// TOP</span></li> <li class="alt"> -<span class="number">0</span>.5f, <span class="number">0</span>.5f, <span class="number">0</span>.5f,</li> <li class=""> <span class="number">0</span>.5f, <span class="number">0</span>.5f, <span class="number">0</span>.5f,</li> <li class="alt"> -<span class="number">0</span>.5f, <span class="number">0</span>.5f, -<span class="number">0</span>.5f,</li> <li class=""> <span class="number">0</span>.5f, <span class="number">0</span>.5f, -<span class="number">0</span>.5f,</li> <li class="alt"> <span class="comment">// BOTTOM</span></li> <li class=""> -<span class="number">0</span>.5f, -<span class="number">0</span>.5f, <span class="number">0</span>.5f,</li> <li class="alt"> -<span class="number">0</span>.5f, -<span class="number">0</span>.5f, -<span class="number">0</span>.5f,</li> <li class=""> <span class="number">0</span>.5f, -<span class="number">0</span>.5f, <span class="number">0</span>.5f,</li> <li class="alt"> <span class="number">0</span>.5f, -<span class="number">0</span>.5f, -<span class="number">0</span>.5f,</li> <li class=""> };</li> <li class="alt"></li> <li class=""> FloatBuffer cubeBuff;</li> <li class="alt"></li> <li class=""> <span class="keyword">float</span> xrot = <span class="number">0</span>.0f;</li> <li class="alt"> <span class="keyword">float</span> yrot = <span class="number">0</span>.0f;</li> <li class=""></li> <li class="alt"> <span class="comment">/**</span></li> <li class=""><span class="comment"> * 将float数组转换存储在字节缓冲数组</span></li> <li class="alt"><span class="comment"> * @param arr</span></li> <li class=""><span class="comment"> * @return</span></li> <li class="alt"><span class="comment"> */</span></li> <li class=""> <span class="keyword">public</span> FloatBuffer makeFloatBuffer(<span class="keyword">float</span>[] arr) {</li> <li class="alt"> ByteBuffer bb = ByteBuffer.allocateDirect(arr.length * <span class="number">4</span>);<span class="comment">//分配缓冲空间,一个float占4个字节</span></li> <li class=""> bb.order(ByteOrder.nativeOrder()); <span class="comment">//设置字节顺序, 其中ByteOrder.nativeOrder()是获取本机字节顺序</span></li> <li class="alt"> FloatBuffer fb = bb.asFloatBuffer(); <span class="comment">//转换为float型</span></li> <li class=""> fb.put(arr); <span class="comment">//添加数据</span></li> <li class="alt"> fb.position(<span class="number">0</span>); <span class="comment">//设置数组的起始位置</span></li> <li class=""> <span class="keyword">return</span> fb;</li> <li class="alt"> }</li> <li class=""></li> <li class="alt"> <span class="keyword">public</span> CubeRenderer() {</li> <li class=""> <span class="comment">// TODO Auto-generated constructor stub</span></li> <li class="alt"> cubeBuff = makeFloatBuffer(box);<span class="comment">//转换float数组</span></li> <li class=""> }</li> <li class="alt"></li> <li class=""></li> <li class="alt"> <span class="keyword">protected</span> <span class="keyword">void</span> init(GL10 gl) {</li> <li class=""> gl.glClearColor(<span class="number">0</span>.0f, <span class="number">0</span>.0f, <span class="number">0</span>.0f, <span class="number">1</span>.0f);<span class="comment">//设置清屏时背景的颜色,R,G,B,A</span></li> <li class="alt"></li> <li class=""> gl.glEnable(GL10.GL_DEPTH_TEST); <span class="comment">//启用深度缓存</span></li> <li class="alt"> gl.glEnable(GL10.GL_CULL_FACE); <span class="comment">//启用背面剪裁</span></li> <li class=""> gl.glClearDepthf(<span class="number">1</span>.0f); <span class="comment">// 设置深度缓存值</span></li> <li class="alt"> gl.glDepthFunc(GL10.GL_LEQUAL); <span class="comment">// 设置深度缓存比较函数,GL_LEQUAL表示新的像素的深度缓存值小于等于当前像素的深度缓存值(通过gl.glClearDepthf(1.0f)设置)时通过深度测试 </span></li> <li class=""> gl.glShadeModel(GL10.GL_SMOOTH);<span class="comment">// 设置阴影模式GL_SMOOTH</span></li> <li class="alt"> }</li> <li class=""></li> <li class="alt"> <span class="annotation">@Override</span></li> <li class=""> <span class="keyword">public</span> <span class="keyword">void</span> onSurfaceCreated(GL10 gl, EGLConfig config) {</li> <li class="alt"> <span class="comment">// TODO Auto-generated method stub</span></li> <li class=""> init(gl);</li> <li class="alt"> }</li> <li class=""></li> <li class="alt"> <span class="annotation">@Override</span></li> <li class=""> <span class="keyword">public</span> <span class="keyword">void</span> onSurfaceChanged(GL10 gl, <span class="keyword">int</span> w, <span class="keyword">int</span> h) {</li> <li class="alt"> <span class="comment">// TODO Auto-generated method stub</span></li> <li class=""> gl.glViewport(<span class="number">0</span>, <span class="number">0</span>, w, h); <span class="comment">//设置视窗</span></li> <li class="alt"> gl.glMatrixMode(GL10.GL_PROJECTION); <span class="comment">// 设置投影矩阵</span></li> <li class=""> gl.glLoadIdentity(); <span class="comment">//设置矩阵为单位矩阵,相当于重置矩阵 </span></li> <li class="alt"> GLU.gluPerspective(gl, <span class="number">45</span>.0f, ((<span class="keyword">float</span>) w) / h, <span class="number">0</span>.1f, 10f);<span class="comment">//设置透视范围 </span></li> <li class=""> }</li> <li class="alt"></li> <li class=""> <span class="annotation">@Override</span></li> <li class="alt"> <span class="keyword">public</span> <span class="keyword">void</span> onDrawFrame(GL10 gl) {</li> <li class=""> <span class="comment">// TODO Auto-generated method stub</span></li> <li class="alt"> gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);<span class="comment">// 清除屏幕和深度缓存</span></li> <li class=""></li> <li class="alt"> gl.glMatrixMode(GL10.GL_MODELVIEW); <span class="comment">//切换至模型观察矩阵</span></li> <li class=""> gl.glLoadIdentity();<span class="comment">// 重置当前的模型观察矩阵</span></li> <li class="alt"> GLU.gluLookAt(gl, <span class="number">0</span>, <span class="number">0</span>, <span class="number">3</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>);<span class="comment">//设置视点和模型中心位置</span></li> <li class=""></li> <li class="alt"> gl.glVertexPointer(<span class="number">3</span>, GL10.GL_FLOAT, <span class="number">0</span>, cubeBuff);<span class="comment">//设置顶点数据</span></li> <li class=""> gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);</li> <li class="alt"></li> <li class=""> gl.glRotatef(xrot, <span class="number">1</span>, <span class="number">0</span>, <span class="number">0</span>); <span class="comment">//绕着(0,0,0)与(1,0,0)即x轴旋转</span></li> <li class="alt"> gl.glRotatef(yrot, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>);</li> <li class=""></li> <li class="alt"> gl.glColor4f(<span class="number">1</span>.0f, <span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span>.0f); <span class="comment">//设置颜色,红色</span></li> <li class=""> gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, <span class="number">0</span>, <span class="number">4</span>); <span class="comment">//绘制正方型FRONT面</span></li> <li class="alt"> gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, <span class="number">4</span>, <span class="number">4</span>);</li> <li class=""></li> <li class="alt"> gl.glColor4f(<span class="number">0</span>, <span class="number">1</span>.0f, <span class="number">0</span>, <span class="number">1</span>.0f);</li> <li class=""> gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, <span class="number">8</span>, <span class="number">4</span>);</li> <li class="alt"> gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, <span class="number">12</span>, <span class="number">4</span>);</li> <li class=""></li> <li class="alt"> gl.glColor4f(<span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span>.0f, <span class="number">1</span>.0f);</li> <li class=""> gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, <span class="number">16</span>, <span class="number">4</span>);</li> <li class="alt"> gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, <span class="number">20</span>, <span class="number">4</span>);</li> <li class=""></li> <li class="alt"> xrot += <span class="number">1</span>.0f;</li> <li class=""> yrot += <span class="number">0</span>.5f;</li> <li class="alt"> }</li> <li class=""></li> <li class="alt">}</li> <li class="alt">