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

效果图如下所示:

时间: 2024-10-16 03:11:42

Android OpenGL 入门示例的相关文章

Android OpenGL入门示例:绘制三角形和正方形 (附完整源码)

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

[转]Android OpenGL ES 开发教程 从入门到精通

本文转自:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ES 简明开发教程一:概述 Android OpenGL ES 简明开发教程二:构造OpenGL ES View Android OpenGL ES 简明开发教程三:3D绘图基本概念 Android OpenGL ES 简明开发教程四:3D 坐标变换 Android OpenGL ES 简明开发教程五

Android基础入门教程——8.3.2 绘图类实战示例

Android基础入门教程--8.3.2 绘图类实战示例 标签(空格分隔): Android基础入门教程 本节引言: 前两节我们学了Bitmap和一些基本的绘图API的属性以及常用的方法,但心里总觉得有点 不踏实,总得写点什么加深下映像是吧,嗯,本节我们就来写两个简单的例子: 1.简单画图板的实现 2.帮美女擦衣服的简单实现 嘿嘿,第二个例子是小猪刚学安卓写的一个小Demo~嘿嘿~ 开始本节内容~ 1.实战示例1:简单画图板的实现: 这个相信大家都不陌生,很多手机都会自带一个给用户涂鸦的画图板,

Android OpenGL ES 开发教程 从入门到精通

From:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ES 简明开发教程一:概述 Android OpenGL ES 简明开发教程二:构造OpenGL ES View Android OpenGL ES 简明开发教程三:3D绘图基本概念 Android OpenGL ES 简明开发教程四:3D 坐标变换 Android OpenGL ES 简明开发教程五

Android基础入门教程——10.12 传感器专题(3)——加速度-陀螺仪传感器

Android基础入门教程--10.12 传感器专题(3)--加速度/陀螺仪传感器 标签(空格分隔): Android基础入门教程 本节引言: 本节继续来扣Android中的传感器,本节带来的是加速度传感器(Accelerometer sensor)以及 陀螺仪传感器(Gyroscope sensor),和上一节的方向传感器一样有着x,y,z 三个轴, 还是要说一点:x,y轴的坐标要和绘图那里的x,y轴区分开来!传感器的是以左下角 为原点的!x向右,y向上!好的,带着我们的套路来学本节的传感器吧

Android基础入门教程——8.1.3 Android中的13种Drawable小结 Part 3

Android基础入门教程--8.1.3 Android中的13种Drawable小结 Part 3 标签(空格分隔): Android基础入门教程 本节引言: 本节我们来把剩下的四种Drawable也学完,他们分别是: LayerDrawable,TransitionDrawable,LevelListDrawable和StateListDrawable, 依旧贴下13种Drawable的导图: 1.LayerDrawable 层图形对象,包含一个Drawable数组,然后按照数组对应的顺序来

Android基础入门教程——8.1.2 Android中的13种Drawable小结 Part 2

Android基础入门教程--8.1.2 Android中的13种Drawable小结 Part 2 标签(空格分隔): Android基础入门教程 本节引言: 本节我们继续来学习Android中的Drawable资源,上一节我们学习了: ColorDrawable:NinePatchDrawable: ShapeDrawable:GradientDrawable!这四个Drawable~ 而本节我们继续来学习接下来的五个Drawable,他们分别是: BitmapDrawable:Insert

Android基础入门教程——2.3.12 Date & Time组件(下)

Android基础入门教程--2.3.12 Date & Time组件(下) 标签(空格分隔): Android基础入门教程 本节引言: 本节我们来继续学习Android系统给我们提供的几个原生的Date & Time组件,他们分别是: DatePicker(日期选择器),TimePicker(时间选择器),CalendarView(日期视图),好吧, 其实一开始让我扣这几个玩意我是拒绝的,因为在我的印象里,他们是这样的: 简直把我丑哭了,有木有,终于知道为什么那么多人喜欢自定义这种类型的

2015年最新Android基础入门教程目录(完结版)

2015年最新Android基础入门教程目录(完结版) 标签(空格分隔): Android基础入门教程 前言: 关于<2015年最新Android基础入门教程目录>终于在今天落下了帷幕,全套教程 共148节已编写完毕,附上目录,关于教程的由来,笔者的情况和自学心得,资源分享 以及一些疑问等可戳:<2015最新Android基础入门教程>完结散花~ 下面是本系列教程的完整目录: 第一章:环境搭建与开发相关(已完结 10/10) Android基础入门教程--1.1 背景相关与系统架构