zoukankan      html  css  js  c++  java
  • Android OpenGL 入门示例----绘制三角形和正方形

    Android上对OpenGl的支持是无缝的,所以才有众多3D效果如此逼真的游戏,在Camera的一些流程中也有用到GLSurfaceView的情况。本文记录OpenGL在Android上的入门级示例,绘制一个三角形和正方形。尽管功能简单,可是我捣腾了好几个晚上,大量网上文章上的代码都有点问题,不是绘制不出来就是挂了。

    第一个文件:MainActivity.java

    package com.example.opentest;
    
    
    import android.opengl.GLSurfaceView;
    import android.os.Bundle;
    import android.app.Activity;
    import android.view.Menu;
    
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            GLSurfaceView glSurfaceView = new GLSurfaceView(this);
            glSurfaceView.setRenderer(new OpenGLRender());
            setContentView(glSurfaceView);
            //setContentView(R.layout.activity_main);
        
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
    }

    第二个文件:BufferUtil.java 负责将数组转成buffer

    package com.example.opentest;
    
    
    
    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.nio.FloatBuffer;
    import java.nio.IntBuffer;
    
    public class BufferUtil {
        public static FloatBuffer mBuffer;
        public static FloatBuffer floatToBuffer(float[] a){
            //先初始化buffer,数组的长度*4,因为一个float占4个字节
            ByteBuffer mbb = ByteBuffer.allocateDirect(a.length*4);
            //数组排序用nativeOrder
            mbb.order(ByteOrder.nativeOrder());
            mBuffer = mbb.asFloatBuffer();
            mBuffer.put(a);
            mBuffer.position(0);
            return mBuffer;
        }
        
        public static IntBuffer intToBuffer(int[] a){
            
            IntBuffer intBuffer;
            //先初始化buffer,数组的长度*4,因为一个float占4个字节
            ByteBuffer mbb = ByteBuffer.allocateDirect(a.length*4);
            //数组排序用nativeOrder
            mbb.order(ByteOrder.nativeOrder());
            intBuffer = mbb.asIntBuffer();
            intBuffer.put(a);
            intBuffer.position(0);
            return intBuffer;
        }
    }

    第三个文件:OpenGLRender.java 这是最为核心的,负责给配套的GLSurfaceView绘制东西

    package com.example.opentest;
    
    
    
    import java.nio.FloatBuffer;
    import javax.microedition.khronos.egl.EGLConfig;
    import javax.microedition.khronos.opengles.GL10;
    import android.opengl.GLSurfaceView.Renderer;
    
    public class OpenGLRender implements Renderer {
    
        private float[] mTriangleArray = {
                0f,1f,0f,
                -1f,-1f,0f,
                1f,-1f,0f
        };
        private FloatBuffer mTriangleBuffer;
    
    
        private float[] mColorArray={
                1f,0f,0f,1f,     //
                0f,1f,0f,1f,     //绿
                0f,0f,1f,1f      //
        };
        private FloatBuffer mColorBuffer;
    
        //正方形的四个顶点
        private FloatBuffer quateBuffer ;
        private float[] mQuateArray = {
                -1f, -1f, 0f,
                1f, -1f, 0f,
                -1f, 1f, 0f,
                1f, 1f, 0f,
        };
    
        @Override
        public void onDrawFrame(GL10 gl) {
            // TODO Auto-generated method stub
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
            //使用数组作为颜色
            gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);
    
            //绘制小三角形
            gl.glLoadIdentity();
            gl.glTranslatef(-1.5f, 0.0f, -6.0f);
            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mTriangleBuffer);//数组指向三角形顶点buffer
            gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
    //        gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
            gl.glFinish();
    
            //绘制正方形
            gl.glLoadIdentity();
            gl.glTranslatef(1.5f, 0.0f, -6.0f);
    //        gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, quateBuffer);
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
            gl.glFinish();
    
    
        }
    
        @Override
        public void onSurfaceChanged(GL10 gl, int w, int h) {
            // TODO Auto-generated method stub
            gl.glViewport(0, 0, w, h);
    
            float ratio = (float) w / h;
            gl.glMatrixMode(GL10.GL_PROJECTION);
            gl.glLoadIdentity();
            gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
            gl.glMatrixMode(GL10.GL_MODELVIEW);
            gl.glLoadIdentity();
        }
    
        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            // TODO Auto-generated method stub
            gl.glShadeModel(GL10.GL_SMOOTH);
            gl.glClearColor(1.0f, 1.0f, 1.0f, 0f);
            gl.glClearDepthf(1.0f);
            gl.glEnable(GL10.GL_DEPTH_TEST);
            gl.glDepthFunc(GL10.GL_LEQUAL);
            gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
    
            mTriangleBuffer = BufferUtil.floatToBuffer(mTriangleArray);
            mColorBuffer = BufferUtil.floatToBuffer(mColorArray);
            quateBuffer = BufferUtil.floatToBuffer(mQuateArray);
    
    
        }
    
    }

    开发要点:

    1、GLSurfaceView可以直接new,也可以放到布局里,本例用的是第一种方法。

    2、一个GLSurfaceView要配套一个Renderer,这个Renderer是一个接口,里面有三个函数。这点跟Surfaceview很像。尤其是其中的onDrawFrame()可以类比为Android里View的onDraw()函数。

    3、绘制的主题在onDrawFrame()函数里,使用以下代码绘制三角形:

    //绘制小三角形
    gl.glLoadIdentity();
    gl.glTranslatef(-1.5f, 0.0f, -6.0f);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mTriangleBuffer);//数组指向三角形顶点
    buffergl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
    // gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
    gl.glFinish();

    需要注意的是,在一些教程上写着绘制完后要gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 清除所设的顶点,这是个错误!一旦调用此句,则什么画不出来了!!!

    然后再绘制正方形:

    //绘制正方形
    gl.glLoadIdentity();
    gl.glTranslatef(1.5f, 0.0f, -6.0f);
    // gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, quateBuffer);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
    gl.glFinish();

    注意绘制三角形之前已经加载了Color:gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);

    如果在绘制完后调用gl.glDisableClientState(GL10.GL_COLOR_ARRAY);的话可以看到三角形一闪而过,正方形都看不到了。这块也是个误解!如果后面通过gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);再次指定颜色,可以看到会以此颜色绘制三角形和正方形。 总而言之,这个onDrawFrame()和View的onDraw()很像,在onDraw里不给paint设颜色,就画。或者画完后,又给颜色设成透明了,结果肯定也是啥都看不到。不明白为啥这么多教程上在绘制完小三角形后非要带:

    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 

    gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

    这两句bug!!!

    关于代码本身涉及的流程就不解释了,参考链接里说的很清楚。

    4、如果正方形四个顶点坐标顺序更换后,画出来的将不是正方形。

    源码链接:http://download.csdn.net/detail/yanzi1225627/7484793

    参考: 链接1 链接2

    效果图如下所示:


  • 相关阅读:
    C# HttpWebRequest 发送SOAP XML
    浅谈HTTP中Get与Post的区别(转)
    WebService的helloworld,服务器端与客户端的Demo(转)----自己建立的Web Project , 而不是Web Service Project,利用WSDD 自己发布
    C#操作XML(转)
    要学习的知识
    Web service是什么?
    暖式切边线和冷式切变线
    python 形状区分市控国控,颜色表示aqi等级
    Linux常用指令---grep(搜索过滤)
    Axis通过wsdd部署Web Service
  • 原文地址:https://www.cnblogs.com/Anita9002/p/4441590.html
Copyright © 2011-2022 走看看