Android Open GL ES - 绘制三角形

2024-05-06 20:48
文章标签 android es 绘制 三角形 open gl

本文主要是介绍Android Open GL ES - 绘制三角形,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

初始化GLSurfaceView

接下来我们将尝试使用OpenGLES绘制一个三角形,首先创建一个Android Studio Project,OpenGLESTriangles
接下来我们来学习初始化Open GL ESMainActivity.java内部代码如下:

@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);}

在Android 4.0以前我们进行Open GL渲染主要依赖于GLSurfaceView这个类,GLSurfaceView实际上创建了一个自持的独立窗体,在View层开放一个接口用于展示OpenGL Surface中的内容,因此它不像普通View一样对旋转,动画等支持的那么良好。在Android 4.0后添加了TextureView用于展示OpenGL Surface,这个View并不像GLSurfaceView一样需要创建一个单独的窗体,这里我们先学习使用GLSurfaceView
MainActivity.java中添加如下代码,用于声明GLSurfaceView对象以及记录当前设置是否支持Open GLES2.0:

private GLSurfaceView mGLSurfaceView;private boolean mRendererSet = false;

随后我们需要判断当前设置是否支持Open GL ES 2.0,如果支持,就初始化GLSurfaceView,如果不支持,就弹出Toast告知用户,具体代码如下:

 /*** help to judge whether device support open gl es version 2.0* @param context* @return true:support 2.0 version,false:do not support 2.0 version*/public static boolean isSupportOpenGLES2(Context context) {ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();return configurationInfo.reqGlEsVersion >= 0x20000 || (VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH_MR1 && (Build.FINGERPRINT.startsWith(FINGERPRINT_GENERIC) || Build.FINGERPRINT.startsWith(FINGERPRINT_UNKNOWN) || Build.MODEL.contains(MODEL_GOOGLE)|| Build.MODEL.contains(MODEL_EMULATOR) || Build.MODEL.contains(MODEL_SDK)));}
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mGLSurfaceView = new GLSurfaceView(this);if (DeviceInfor.isSupportOpenGLES2(this)){mGLSurfaceView.setEGLContextClientVersion(2);mGLSurfaceView.setRenderer(new TriangleRenderer(this));mRendererSet = true;}else {Toast.makeText(this, "This Device does not support open gl es 2.0 version!", Toast.LENGTH_SHORT).show();return;}setContentView(mGLSurfaceView);}

由于GLSurfaceView是连接Open GL ESAndroid View之间的桥梁,所以它和Android组件一样,拥有完整的生命周期函数,在初始化后需要管理它的生命周期,代码如下:

@Overrideprotected void onPause() {super.onPause();if (mRendererSet){mGLSurfaceView.onPause();}}@Overrideprotected void onResume() {super.onResume();if (mRendererSet){mGLSurfaceView.onResume();}}

在完成基本的GLSurfaceView创建后,我们来了解一些关于Open Gl ES的基础知识。

Open Gl ES基础

1.在Open Gl ES中只支持三种基本图形,点,线和三角形,所有复杂图形均由这三者绘制而成。
2.在Open Gl ES中绘制图形依赖于渲染器(Renderer),在渲染器中完成图形渲染。在渲染器中使用着色器对图形的每一个位置进行着色,在Open Gl ES中有两类着色器,顶点着色器(VertexShader)和片段着色器(FragmentShader),在渲染器中通过加载,编译着色器,链接程序来完成图形渲染。
按照上文所说我们接下来定义三角形的顶点信息,以及着色器文件。

三角形与着色器(Shader)

接下来为我们的项目添加渲染器(Renderer),代码如下:

public class TriangleRenderer implements Renderer {public static final String TAG = "TriangleRenderer";private Context mContext;public TriangleRenderer(Context context) {mContext = context;}@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {}@Overridepublic void onDrawFrame(GL10 gl) {}
}

在Open Gl ES中,其使用的是世界坐标系(即绝对坐标系),附图如下:
这里写图片描述
在该坐标系中,坐标原点位于屏幕中心,XYZ三轴符合右手法则,我们定义三角形的顶点信息如下(PS:不考虑Z轴):

float[] vertexTrangles = {-1.0f, -1.0f,1.0f, -1.0f,0f, 1.0f};

定义存储三角形的Buffer信息如下:

private static final int BYTES_PER_FLOAT = 4;//每个Float占四个字节
private FloatBuffer vertexData;//存储顶点数据的Buffer
private static final int POSITION_COMPONENT_COUNT = 2;//代表点坐标的个数

将上述代码写入渲染器中,在渲染器的构造函数中为三角形顶点初始化缓存大小,代码如下:

vertexData = ByteBuffer.allocateDirect(vertexTrangles.length * BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();vertexData.put(vertexTrangles);

随后编写Open Gl ES着色器文件,在res目录下新建raw文件夹,并新建simple_vertex_shader.glsl文件,内容如下:

attribute vec4 a_Position;
#定义一个点的位置信息
void main(){gl_Position = a_Position;
}

新建simple_fragement_shader.glsl文件,内容如下:

#数据类型
precision mediump float;
#片段着色器中的色值
uniform vec4 u_Color;void main(){gl_FragColor = u_Color;
}

加载编译Shader,链接程序

从资源文件中读取glsl文件转化成String,工具函数如下:

 /*** read glsl file from resource* @param context* @param resourceId example R.raw.vertex_shader* @return*/public static String readTextFileFromResource(Context context,int resourceId){StringBuilder body = new StringBuilder();try {InputStream inputStream = context.getResources().openRawResource(resourceId);InputStreamReader inputStreamReader = new InputStreamReader(inputStream);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String nextLine;while ((nextLine = bufferedReader.readLine()) != null){body.append(nextLine);body.append('\n');}} catch (IOException e) {e.printStackTrace();}return body.toString();}

编译着色器文件,代码如下:

public static int compileVertexShader(String shaderCode) {return compileShader(GL_VERTEX_SHADER, shaderCode);}public static int compileFragmentShader(String shaderCode) {return compileShader(GL_FRAGMENT_SHADER, shaderCode);}private static int compileShader(int type, String shaderCode) {int shaderObjectId = glCreateShader(type);if (shaderObjectId == 0) {return 0;}glShaderSource(shaderObjectId, shaderCode);glCompileShader(shaderObjectId);final int[] compileStatus = new int[1];glGetShaderiv(shaderObjectId, GL_COMPILE_STATUS, compileStatus, 0);if (compileStatus[0] == 0) {glDeleteShader(shaderObjectId);return 0;}return shaderObjectId;}

随后我们在渲染器中完成程序的构建使用,核心代码如下:

 @Overridepublic void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {gl10.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);//加载Shader fileString vertexShaderSource = TextResourceReader.readTextFileFromResource(mContext, R.raw.simple_vertex_shader);String fragmentShaderSource = TextResourceReader.readTextFileFromResource(mContext, R.raw.simple_fragment_shader);//编译Shaderint vertexShader = ShaderHelper.compileVertexShader(vertexShaderSource);int fragmentShader = ShaderHelper.compileFragmentShader(fragmentShaderSource);//链接程序mProgramId = ShaderHelper.linkProgram(vertexShader, fragmentShader);//验证程序ShaderHelper.validateProgram(mProgramId);//使用程序glUseProgram(mProgramId);//查找颜色片元位置uColorLocation = glGetUniformLocation(mProgramId, U_COLOR);//查找顶点片元位置aPositionLocation = glGetAttribLocation(mProgramId, A_POSITION);//重置数据集位置vertexData.position(0);//读取顶点信息并渲染glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT, false, 0,vertexData);glEnableVertexAttribArray(aPositionLocation);}

以上代码中的链接程序函数源码如下:

public static int linkProgram(int vertexShaderId, int fragmentShaderId) {int programId = glCreateProgram();if (programId == 0) {return 0;}//完成着色器和程序之间的绑定glAttachShader(programId, vertexShaderId);glAttachShader(programId, fragmentShaderId);//链接程序glLinkProgram(programId);final int[] linkStatus = new int[1];glGetProgramiv(programId, GL_LINK_STATUS, linkStatus, 0);if (linkStatus[0] == 0) {glDeleteProgram(programId);return 0;}return programId;}public static boolean validateProgram(int programId) {glValidateProgram(programId);final int[] validateStatus = new int[1];glGetProgramiv(programId, GL_VALIDATE_STATUS, validateStatus, 0);return validateStatus[0] != 0;}

绘制三角形

修改渲染器中代码如下:

 @Overridepublic void onSurfaceChanged(GL10 gl10, int i, int i1) {gl10.glViewport(0, 0, i, i1);}@Overridepublic void onDrawFrame(GL10 gl10) {gl10.glClear(gl10.GL_COLOR_BUFFER_BIT);//传入片元颜色值,可以通过改变最后四个参数值参看片元渲染后的颜色变化glUniform4f(uColorLocation, 1.0f, 1.0f, 1.0f, 1.0f);//绘制三角形glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);}

运行截图如下:
这里写图片描述

最新文章更新在微信公众号上,欢迎关注获取详情:
这里写图片描述

完整代码Github地址这里写链接内容

这篇关于Android Open GL ES - 绘制三角形的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/965345

相关文章

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

Android WebView无法加载H5页面的常见问题和解决方法

《AndroidWebView无法加载H5页面的常见问题和解决方法》AndroidWebView是一种视图组件,使得Android应用能够显示网页内容,它基于Chromium,具备现代浏览器的许多功... 目录1. WebView 简介2. 常见问题3. 网络权限设置4. 启用 JavaScript5. D

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

SpringBoot整合easy-es的详细过程

《SpringBoot整合easy-es的详细过程》本文介绍了EasyES,一个基于Elasticsearch的ORM框架,旨在简化开发流程并提高效率,EasyES支持SpringBoot框架,并提供... 目录一、easy-es简介二、实现基于Spring Boot框架的应用程序代码1.添加相关依赖2.添

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干