Android APP OpenGL ES应用(01)GLSurfaceView 2D/3D绘图基础

这篇具有很好参考价值的文章主要介绍了Android APP OpenGL ES应用(01)GLSurfaceView 2D/3D绘图基础。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 Android 3D图形基础简介

1.1 OpenGL ES简介

OpenGL本身是开放图形库的一种标准,定义了一个跨语言、跨平台的编程规范,主要用于3D图形编程。OpenGLES是OpenGL的裁剪版本,主要是针对嵌入式设备/移动设备(像手机、游戏机这种等等。。。)进行裁剪后的库。对于Android设备来说主要是用OpenGL ES。从初学者角度来讲 OpenGLES和OpenGL差别不大。

OpenGL主要使用GPU进行绘图,关于CPU和GPU的对比如下所示:

  • CPU:计算量小,适用于复杂逻辑运算场合,适合迭代计算,通用处理器。
  • GPU :计算量大,适用于规模简单计算场合,适合并行运算,附属处理器。

关于OpenGL基础内容以及更多了解可关注 系列文章:专题分纲目录 OpenGL教程。

Android 中提供了GLSurfaceView组件来用于现显示2D和3D图形(注意:GLSurfaceView本身并不提供绘制3D图形的功能,而是由GLSurfaceView.Render来完成SurfaceView中3D图形的绘制)

1.2 GLSurfaceView解读

GLSurfaceView主要用于显示,GLSurfaceView.Render主要用于渲染,GL10类主要用于OpenGLES的具体操作,操作的流程相对繁琐,需要对OpenGL本身有一定了解,因此建议先查看系列文章 专题分纲目录 OpenGL教程。再来研究GL10部分代码,相关文档梳理如下:

  • GLSurfaceView 官方文档:Android GLSurfaceView类 详细解读
  • GLSurfaceView.Render 官方文档:Android GLSurfaceView.Render类 详细解读
  • GLSurfaceView的中用于操作OpenGLES的关键类为GL10,在代码中使用最多,因此也做相关解读,GLSurfaceView关键类GL10官方文档:Android OpenGLES关键类GL10 详细解读

关于具体绘制说明:OpenGL ES只能绘制三角形组成的3D图形,而OpenGL可以绘制四边形和多边形组成的3D图形。

2 GLSurfaceView 2D实战

2.1 静态三角形

实现功能:使用GL10(OpenGLES的关键类)在屏幕上显示一个三角形。

Android APP OpenGL ES应用(01)GLSurfaceView 2D/3D绘图基础

关于该程序,自定义MyRender的代码实现如下所示:

class MyRender implements GLSurfaceView.Renderer {
    //定义顶点坐标,用于顶点着色器 Vertex Shader
    private float[] triangleData = new float[] {
            0.0f, 0.5f , 0.0f ,  //上顶点
            -0.5f, 0.0f , 0.0f , //左顶点
            0.5f, 0.0f , 0.0f    //右顶点
    };

    //定义颜色数组,用于片段着色器 Fragment Shader
    private int[] triangleColor = new int[] {
            0xffff,0x0,0x0,0x0, // 上顶点红色
            0x0,0xffff,0x0,0x0, // 左顶点绿色
            0x0,0x0,0xffff,0x0  // 右顶点蓝色
    };

    //用于数据转换
    private FloatBuffer triangleDataBuffer;
    private IntBuffer triangleColorBuffer;

    public MyRender(){
        //将Vertex Shader数据转换成FloatBuffer
        triangleDataBuffer = BufferUtil.floatBufferUtil(triangleData);
        //将Fragment Shader数据转换成IntBuffer
        triangleColorBuffer = BufferUtil.intBufferUtil(triangleColor);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        gl.glDisable(GL10.GL_DITHER);//关闭防抖
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT//设置透视修正
                , GL10.GL_FASTEST);
        gl.glClearColor(0, 0, 0, 0);
        gl.glShadeModel(GL10.GL_SMOOTH);// 设置为阴影平滑模式
        gl.glEnable(GL10.GL_DEPTH_TEST);// 启用深度测试
        gl.glDepthFunc(GL10.GL_LEQUAL);// 设置深度测试的类型
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height); //设置3D视窗的大小及位置
        gl.glMatrixMode(GL10.GL_PROJECTION); //设置矩阵模式设为投影矩阵
        gl.glLoadIdentity(); //初始化单位矩阵
        float ratio = (float) width / height; //计算视窗宽高比
        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);//设置视窗空间大小
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);//启用vertex shader 数据
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);//启用fragment shader数据
        gl.glMatrixMode(GL10.GL_MODELVIEW);//设置当前矩阵堆栈为模型堆栈

        gl.glLoadIdentity();
        gl.glTranslatef(0.0f, 0.0f, -1.2f);  // 该平移方法用于把图形绘制到可视区域
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleDataBuffer);//设置vertex shader 数据
        gl.glColorPointer(4, GL10.GL_FIXED, 0, triangleColorBuffer);//设置 fragment shader数据
        gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);//根据vertex shader 和 fragment shader数据来 绘制图形
        gl.glFinish();//绘制结束
        gl.glDisableClientState(GL10.GL_COLOR_ARRAY);//禁用fragment shader 数据
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);//禁用vertex shader 数据
    }
}

代码中涉及到的工具类 BufferUtil 它的实现如下所示:

public class BufferUtil {
    //将int[]数组转换为OpenGLES所需的IntBuffer
    public static IntBuffer intBufferUtil(int[] arr)
    {
        IntBuffer buffer;
        // 初始化ByteBuffer,长度为arr数组的长度*4,因为一个int占4字节
        ByteBuffer bb = ByteBuffer.allocateDirect(arr.length * 4);
        bb.order(ByteOrder.nativeOrder()); //数组排列用nativeOrder
        buffer = bb.asIntBuffer();
        buffer.put(arr);
        buffer.position(0);
        return buffer;
    }
    //将float[]数组转换为OpenGLES所需的FloatBuffer
    public static FloatBuffer floatBufferUtil(float[] arr)
    {
        FloatBuffer buffer;
        //初始化ByteBuffer,长度为arr数组的长度*4,因为一个float占4字节
        ByteBuffer bb = ByteBuffer.allocateDirect(arr.length * 4);
        bb.order(ByteOrder.nativeOrder());
        buffer = bb.asFloatBuffer();
        buffer.put(arr);
        buffer.position(0);
        return buffer;
    }
}

在MainActivity中实现代码为:

public class MainActivity extends AppCompatActivity  {
    private static String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        GLSurfaceView glSurfaceView = new GLSurfaceView(this);
        MyRender myRender = new MyRender();
        glSurfaceView.setRenderer(myRender);
        setContentView(glSurfaceView);
    }
}

2.2 旋转三角形

实现功能:效果如下所示(绕Z轴旋转)

Android APP OpenGL ES应用(01)GLSurfaceView 2D/3D绘图基础

2.1的基础上添加如下代码,如下所示(关注+部分即可)

class MyRender implements GLSurfaceView.Renderer {
    //...
+   private float rotate = 0.0f;
    //...
    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);//启用vertex shader 数据
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);//启用fragment shader数据
        gl.glMatrixMode(GL10.GL_MODELVIEW);//设置当前矩阵堆栈为模型堆栈

        gl.glLoadIdentity();
        gl.glTranslatef(0.0f, 0.0f, -1.1f);  // 该平移方法用于把图形绘制到可视区域
+       gl.glRotatef(rotate,0.0f,0.0f,-1.1f);//沿着Z轴旋转
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleDataBuffer);//设置vertex shader 数据
        gl.glColorPointer(4, GL10.GL_FIXED, 0, triangleColorBuffer);//设置 fragment shader数据
        gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);//根据vertex shader 和 fragment shader数据来 绘制图形
        gl.glFinish();//绘制结束
        gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
+       rotate++;
    }
    //...
}

3 GLSurfaceView 3D实战 旋转彩色立方体

实现功能:效果如下所示(绕(1,1)向量轴旋转)

Android APP OpenGL ES应用(01)GLSurfaceView 2D/3D绘图基础

关于该程序,自定义MyRender的代码实现如下所示:

class MyRender implements GLSurfaceView.Renderer {
    // 定义立方体的8个顶点
    float[] cubeVertices = new float[] {
            // 前面 正方形的4个顶点
            0.5f, 0.5f, 0.5f,
            0.5f, -0.5f, 0.5f,
            -0.5f, -0.5f, 0.5f,
            -0.5f, 0.5f, 0.5f,
            // 后面 正方形的4个顶点
            0.5f, 0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, 0.5f, -0.5f
    };

    // 定义立方体的8个顶点的颜色,分别对应上面8个顶点
    int[] cubeColors = new int[]{
            0xffff,0x0,0x0,0x0,   //红色
            0x0,0xffff,0x0,0x0,   //绿色
            0x0,0x0,0xffff,0x0,   //蓝色
            0xffff,0xffff,0x0,0x0,//黄色
            0xffff,0x0,0x0,0x0,   //红色
            0x0,0xffff,0x0,0x0,   //绿色
            0x0,0x0,0xffff,0x0,   //蓝色
            0xffff,0xffff,0x0,0x0,//黄色
    };

    // 定义立方体 6个面(12个三角形所需的顶点)
    private byte[] cubeFacets = new byte[]{
            0, 1, 2,0, 2, 3,
            2, 3, 7,2, 6, 7,
            0, 3, 7,0, 4, 7,
            4, 5, 6,4, 6, 7,
            0, 1, 4,1, 4, 5,
            1, 2, 6,1, 5, 6,
    };

    // 定义Open GL ES绘制所需要的Buffer对象
    FloatBuffer cubeVerticesBuffer;
    ByteBuffer cubeFacetsBuffer;
    IntBuffer cubeColorsBuffer;
    private float rotate = 0.0f;

    public MyRender(){
        // 将立方体的顶点位置数据数组包装成FloatBuffer
        cubeVerticesBuffer = BufferUtil.floatBufferUtil(cubeVertices);
        // 将立方体的6个面(12个三角形)的数组包装成ByteBuffer
        cubeFacetsBuffer = ByteBuffer.wrap(cubeFacets);
        cubeColorsBuffer = BufferUtil.intBufferUtil(cubeColors);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        gl.glDisable(GL10.GL_DITHER);//关闭防抖
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT//设置透视修正
                , GL10.GL_FASTEST);
        gl.glClearColor(0, 0, 0, 0);
        gl.glShadeModel(GL10.GL_SMOOTH);// 设置为阴影平滑模式
        gl.glEnable(GL10.GL_DEPTH_TEST);// 启用深度测试
        gl.glDepthFunc(GL10.GL_LEQUAL);// 设置深度测试的类型
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height); //设置3D视窗的大小及位置
        gl.glMatrixMode(GL10.GL_PROJECTION); //设置矩阵模式设为投影矩阵
        gl.glLoadIdentity(); //初始化单位矩阵
        float ratio = (float) width / height; //计算视窗宽高比
        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);//设置视窗空间大小
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);//启用vertex shader 数据
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);//启用fragment shader数据
        gl.glMatrixMode(GL10.GL_MODELVIEW);//设置当前矩阵堆栈为模型堆栈

        gl.glLoadIdentity();
        gl.glTranslatef(0.0f, 0.0f, -5f);
        gl.glRotatef(rotate, 1.0f, 1.0f, 0f);// 沿着(1,1)向量为轴的方向旋转
        // 设置顶点的位置数据
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, cubeVerticesBuffer);
        // 设置顶点的颜色数据
        gl.glColorPointer(4, GL10.GL_FIXED, 0, cubeColorsBuffer);
        // 按cubeFacetsBuffer指定的面绘制三角形
        gl.glDrawElements(GL10.GL_TRIANGLE_STRIP,cubeFacetsBuffer.remaining(),GL10.GL_UNSIGNED_BYTE, cubeFacetsBuffer);

        gl.glFinish();//绘制结束
        gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        rotate++;
    }
}

代码中涉及到的工具类 BufferUtil  和 MainAciivity代码同2.1 相同,这里不再重复。文章来源地址https://www.toymoban.com/news/detail-419716.html

到了这里,关于Android APP OpenGL ES应用(01)GLSurfaceView 2D/3D绘图基础的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenGL ES相关库加载3D 车辆模型

    需求类似奇瑞的这个效果,就是能全方位旋转拖拽看车,以及点击开关车门车窗后备箱等 瑞虎9全景看车 (chery.cn) 最开始收到这个需求的时候还有点无所适从,因为以前没有做过类似的效果,后面一经搜索后发现实现的方式五花八门,但始终绕不过opengl,于是通过opengl 逐步展

    2024年02月06日
    浏览(36)
  • 【Android OpenGL开发】OpenGL ES与EGL介绍

    OpenGL(Open Graphics Library)是一个跨编程语言、跨平台的编程图形程序接口,主要用于图像的渲染。 Android提供了简化版的OpenGL接口,即OpenGL ES。 早先定义 OpenGL ES 是 OpenGL 的嵌入式设备版本,用于移动端平台(Android、iOS),但由于嵌入式设备要求的是高性能,所以一些其它纯

    2024年02月04日
    浏览(89)
  • Android OpenGL ES 学习(八) –矩阵变换

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投影 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序 Android OpenG

    2023年04月08日
    浏览(40)
  • Android OpenGL ES 学习(一) -- 基本概念

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投屏 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序 Android OpenG

    2024年01月23日
    浏览(43)
  • Android OpenGL ES 学习(四) -- 正交投影

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投屏 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序 Android OpenG

    2024年02月13日
    浏览(42)
  • Android OpenGL ES 学习(五) -- 渐变色

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投屏 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序 Android OpenG

    2024年02月07日
    浏览(40)
  • Python使用Matplotlib绘图2维+3维(2D图像和3D图像),去理解考研积分(或者二重积分)

    绘制折线图(plt.plot) 设置图片大小和分辨率(plt.figure) 保存图片到本地(plt.savefig) 设置xy轴刻度和字符串(xticks、yticks) 设置标题、xy轴标签(title、xlable、ylable) 其他图像类型(散点图plt.scatter,条形图plt.bar,横向plt.barh,直方图plt.hist(bin.width组距、num_bins分多少组、

    2023年04月08日
    浏览(38)
  • Android OpenGL ES实现简单绿幕抠图

    目录 正文 OES Filter BlendShader Filter 最后的效果 缺陷 实现绿幕抠图,其实想法很简单。 这里简单粗暴的使用着色器替换。 OES Filter 直接实现在相机预览上的Shader ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #extension GL_OES_EGL_image_external : require precision mediump float ;        

    2024年02月13日
    浏览(31)
  • LearnOpenGL - Android OpenGL ES 3.0 绘制三角形

    LearnOpenGL 笔记 - 入门 01 OpenGL LearnOpenGL 笔记 - 入门 02 创建窗口 LearnOpenGL 笔记 - 入门 03 你好,窗口 LearnOpenGL 笔记 - 入门 04 你好,三角形 OpenGL - 如何理解 VAO 与 VBO 之间的关系 经过一段时间 OpenGL 的学习,我们已经掌握了如何使用 glwf 在桌面端绘制简单图形。现在让我们把目光

    2024年02月12日
    浏览(40)
  • OpenGL ES 2.0 for Android教程(二):定义顶点和着色器

    文章传送门 OpenGL ES 2.0 for Android教程(一) OpenGL ES 2.0 for Android教程(三) OpenGL ES 2.0 for Android教程(四) OpenGL ES 2.0 for Android教程(五) OpenGL ES 2.0 for Android教程(六) OpenGL ES 2.0 for Android教程(七) OpenGL ES 2.0 for Android教程(八) OpenGL ES 2.0 for Android教程(九) 本章介绍我们

    2023年04月14日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包