Android OpenGL 基础入门

  Android 自从2.2 版本之后之后开始支持OpenGL,在没有支持OpenGL 的 GPU的情况下,也可以使用(通过软件来模拟)。在Android上使用Opengl操作的对象是GLSurfaceView,这是一个继承自View的扩展。

  在Android上Opengl是通过Vertex Shader 和 Fragment Shader 这两种定点着色器程序来实现图片的加载和渲染的,中文称为定点着色器和片段着色器。一个完整的Opengl程序需要创建定点着色器和片段着色器并将他们Link起来组成一个完整的OpenGL程序。

  顶点着色器的作用是为每一个顶点生成坐标,因此每个顶点都要运行一遍顶点着色器程序,一旦顶点坐标计算出来之后,OpenGL就能够使用这些顶点来组成点,线,和三角形。所有任意的图形都是由这三种基本元素来描述的。下图是顶点着色器进行坐标转换的过程(稍微有点复杂):

  

  这个过程包含了从原始的对象坐标经过模型视图转换生成眼坐标,再经过投影转换生成裁剪坐标,再通过w坐标的归一化转换成为NDC(顶点坐标由(x,y,z,w)构成,在shader程序中一般用一个四维向量vec4来描述),最终通过视口变换生成屏幕坐标显示在屏幕上。这一系列的转换都是通过矩阵来完成的,转换过程和原理是Opengl的精华内容,对于需要进入3D世界的同学需要掌握。在2D世界中我们只需要了解NDC就行了,这里就把NDC叫做OpenGL 坐标,加上Normalized 的修饰是因为这些坐标的值都在(-1,1)之间,OpenGL坐标表示见下图:

  OpenGL坐标原点在屏幕中央,左右坐标范围为[-1,1],在2d环境中坐标值只存在(x,y),并且坐标范围都只能在-1 到 1之间,屏幕中心坐标为(0,0)。因此如果需要指定一张图片的显示位置,指定坐标需要根据这个坐标系来,此外为了保证图片显示比例(长宽比例),在portrait 到 landscape 之间变换的时候一般需要乘以一个aspectRatio (width / height) 来重新设定坐标值。

  了解了Opengl坐标,在来了解一下屏幕坐标(屏幕坐标的坐标原点在左上角)和纹理坐标(纹理坐标的坐标原点在左下角):

屏幕坐标系                

  纹理坐标系

  片段着色器的作用是为点,线或者三角形的每一个顶点的片段(Fragment)生成渲染后的最终颜色。片段就是一个小的单色矩形区域,可以简单的认为是屏幕上的一个像素点。

  以上基本知识基本上可以处理Opengl实现2D图像的绘制和处理。下面来简单看一下Shader的写法,在Android平台上Shader程序一般以字符串的形式出现,或者在res/raw/目录下以*.glsl的格式出现,如果是以单独的文件出现,需要定义专门的文件读入接口来加载Shader程序。这里就介绍一下字符串的形式的Shader程序,来看下面简单的Vertex Shader 和 Fragment Shader:

    private static final String VERTEX_SHADER =
        "attribute vec4 a_position;\n" +
        "attribute vec2 a_texcoord;\n" +
        "varying vec2 v_texcoord;\n" +
        "void main() {\n" +
        "  gl_Position = a_position;\n" +
        "  v_texcoord = a_texcoord;\n" +
        "}\n";

    private static final String FRAGMENT_SHADER =
        "precision mediump float;\n" +
        "uniform sampler2D tex_sampler;\n" +
        "varying vec2 v_texcoord;\n" +
        "void main() {\n" +
        "  gl_FragColor = texture2D(tex_sampler, v_texcoord);\n" +
        "}\n";

  先看一下VERTEX_SHADER,定义了两种类型的变量 atrribute 和 varying。

  其中 attribute变量是只能在vertex shader中使用的变量。(它不能在fragment shader中声明attribute变量,也不能被fragment shader中使用),一般用attribute变量来表示一些顶点的数据,这些顶点数据包含了顶点坐标,法线,纹理坐标,顶点颜色等。应用中一般用函数glBindAttribLocation()来绑定每个attribute变量的位置,然后用函数glVertexAttribPointer()为每个attribute变量赋值。

  varying被称为易变量,一般用于从Vertex Shader 向 Fragment Shader传递数据,上面例子中在VertexShader中定义了attribute 类型的二维向量a_texcoord,并将该值赋值给varying类型的二维向量 v_texcoord。此外对于Vertex Shader 在main() 中必须将顶点坐标赋值给系统变量gl_Position。

  看一下FRAGMENT_SHADER,定义了两种类型的变量,uniform 和 varying。此外还多了一句 precision mediump float,这句话用于定义数据精度,Opengl中可以设置三种类型的精度(lowp,medium 和 highp),对于Vertex Shader来说,Opengl使用的是默认最高精度级别(highp),因此没有定义。

  uniform变量是APP序传递给(vertex和fragment)shader的变量。通过函数glUniform**()函数赋值的。 在(vertex和fragment)shader程序内部,uniform变量就像是C语言里面的常量(const ),它不能被shader程序修改(shader只能用,不能改)。如果uniform变量在vertex和fragment两者之间声明方式完全一样,则它可以在vertex和fragment共享使用。 (相当于一个被vertex和fragment shader共享的全局变量)uniform变量一般用来表示:变换矩阵,材质,光照参数和颜色等信息。

  对于Fragment Shader也需对gl_FragColor赋值。

  现在对基本的Shader有了了解,来看一下Android怎么使用Shader程序。先说明一下Opengl中的资源一般都是用一个句柄(handle)来引用,句柄一般由gl***接口返回,代表一个特定的资源。

  在Android上使用gl,需要用到一些列接口,这里按照一般的调用顺序来列一下基本的接口(暂不包含错误处理)

  1. 和创建Shader相关的:glCreateShader -> glShaderSource -> glCompileShader , 通过这几个接口的调用最终返回一个Shader的句柄

  2. 和创建Shader程序相关的(每个shader程序都必须包含Vertex Shader 和 Fragment Shader两部分):glCreateProgram -> glAttachShader -> glLinkProgram,通过这些接口的调用最终返回个Program的句柄。

  3. 获取Shader内部变量赋值和传递数据到gl,对于不同类型的数据使用不同的接口:GLES20.glGetUniformLocation(mProgram, "tex_sampler"),GLES20.glGetAttribLocation(mProgram, "a_texcoord"),以上两个接口中mProgram 代表glCreateProgram返回的 Shader程序句柄,“a_texcoord”和"tex_sampler"是 Vertex Shader和 Fragment Shader中定义的变量,通过这两个接口获取了变量的句柄,便于向这些变量中传入值。获得变量的句柄之后就要向其中传值,一般通过glVertexAttribPointer()来完成,详细参数这里没有列出,在实例代码中可以学习一下,传值之后需要使glEnableVertexAttribArray才能将数据传入到gl中,传入数据使用glDrawArrays() 。

  这里介绍了Opengl的基本知识,下一篇结合实例介绍一下Opengl在Android上的使用。

时间: 2024-10-29 20:01:31

Android OpenGL 基础入门的相关文章

Android OpenGL ES 入门系列(一) --- 了解OpenGL ES的前世今生

转载请注明出处 本文出自Hansion的博客 OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机.PDA和游戏主机等嵌入式设备而设计,主要用来开发3D图形应用 Android支持以下几个版本的OpenGL ES API: OpenGL ES 1.0和1.1      支持Android 1.0及更高版本 OpenGL ES 2.0               支持Android 2.2(API级别8)及更高版本 O

android的基础入门

一. A通信技术 1. 1G  仅限语音的蜂窝式通话标准 2. 2G  (时分多路复用)数字语音传输技术和增加接收数据的功能 3. 3G  传输声音和数据的速度有很大的 提升 4. 4G  传输高质量的视频和图像,速度很快,无线网的高速发展 B通信方式 1. TDMA  时分多路复用 2.  FDMA 频分多路复用 3. CDMA  码分多路复用 二. A androoid的起源 1. 被安迪:鲁宾所开发,2005年被谷歌收购,安卓的发展史更新换代很快 B android的体系结构 1. app

完整Android开发基础入门博客专栏

博客地址:http://www.runoob.com/w3cnote/android-tutorial-contents.html

Android 开发基础入门篇: 复制一个工程作为一个新的工程

说明 咱们做项目很多时候都需要复制一份工程出来作为一个新的工程 把第一节的工程拷贝到这一节 修改工程名字 打开软件导入此工程 修改包名 第一节的时候说了,一个APP一个包名 自行添加修改 自行修改 自行修改 选择 Sync Now 清理下工程 然后安装到手机 原文地址:https://www.cnblogs.com/yangfengwu/p/11909225.html

Android零基础入门第64节:揭开RecyclerView庐山真面目

大家还记得之前在第38期~第50期都在学习列表控件吗,其中用了8期讲ListView的使用,相信都已经掌握好了吧.那么本期一起来学习Android 5.X新增的一个列表组件,那就是RecyclerView的使用. 一.RecyclerView概述 从前面的学习我们知道,ListView的功能非常强大,几乎绝大部分应用程序都会使用到,虽然也学会一些方法技巧来提升ListView的效率,但其性能还是不是很完美. 另外ListView的可扩展性相对来说比较弱,以前要实现每个列表项的高度不同的界面,或者

Android零基础入门第61节:滚动视图ScrollView

原文:Android零基础入门第61节:滚动视图ScrollView 前面几期学习了ProgressBar系列组件.ViewAnimator系列组件.Picker系列组件和时间日期系列组件,接下来几期继续来学习常见的其他组件. 一.ScrollView概述 从前面的学习有的同学可能已经发现,当拥有很多内容时屏幕显示不完,显示不全的部分完全看不见.但是在实际项目里面,很多内容都不止一个屏幕宽度或高度,那怎么办呢?那就需要本节学习的ScrollView来完成. 在默认情况下,ScrollView只是

Android零基础入门第60节:日历视图CalendarView和定时器Chronometer

原文:Android零基础入门第60节:日历视图CalendarView和定时器Chronometer 上一期学习了AnalogClock.DigitalClock和TextClock时钟组件,本期继续来学习日历视图CalendarView和定时器Chronometer. 一.CalendarView 日历视图(CalendarView)可用于显示和选择日期,用户既可选择一个日期,也可通过触 摸来滚动日历.如果希望监控该组件的日期改变,则可调用CalendarView的 setOnDateCha

Android零基础入门第62节:搜索框组件SearchView

原文:Android零基础入门第62节:搜索框组件SearchView 一.SearchView概述 SearchView是搜索框组件,它可以让用户在文本框内输入文字,并允许通过监听器监控用户输入,当用户输入完成后提交搜索时,也可通过监听器执行实际的搜索. SearchView默认是展示一个search的icon,点击icon展开搜索框,也可以自己设定图标.用SearchView时可指定如下表所示的常见XML属性及相关方法. 如果为SearchView增加一个配套的ListView,则可以为Se

Android零基础入门第16节:Android用户界面开发概述

相信通过前面15期的学习,Android的开发环境已经基本掌握了,如果仍有问题,欢迎到Android零基础入门技术讨论微信群交流,从本期开始正式来一步一步踏入Android开发之路. Android应用开发的一项内容就是用户界面的开发.Android提供了非常丰富的用户界面组件,借助于这些用户界面组件,开发者可以非常方便地进行用户界面开发,而且可以开发出非常优秀的用户界面. 一.界面UI元素介绍 Android应用是运行于手机系统上的程序,这种程序给用户的第一印象就是用户界面.接下来从以下几个方