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学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

QT6中绘制UI的两种方法详解与示例代码

《QT6中绘制UI的两种方法详解与示例代码》Qt6提供了两种主要的UI绘制技术:​​QML(QtMeta-ObjectLanguage)​​和​​C++Widgets​​,这两种技术各有优势,适用于不... 目录一、QML 技术详解1.1 QML 简介1.2 QML 的核心概念1.3 QML 示例:简单按钮

Android NDK版本迭代与FFmpeg交叉编译完全指南

《AndroidNDK版本迭代与FFmpeg交叉编译完全指南》在Android开发中,使用NDK进行原生代码开发是一项常见需求,特别是当我们需要集成FFmpeg这样的多媒体处理库时,本文将深入分析A... 目录一、android NDK版本迭代分界线二、FFmpeg交叉编译关键注意事项三、完整编译脚本示例四

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

Android 实现一个隐私弹窗功能

《Android实现一个隐私弹窗功能》:本文主要介绍Android实现一个隐私弹窗功能,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 效果图如下:1. 设置同意、退出、点击用户协议、点击隐私协议的函数参数2. 《用户协议》、《隐私政策》设置成可点击的,且颜色要区分出来res/l

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android 12解决push framework.jar无法开机的方法小结

《Android12解决pushframework.jar无法开机的方法小结》:本文主要介绍在Android12中解决pushframework.jar无法开机的方法,包括编译指令、框架层和s... 目录1. android 编译指令1.1 framework层的编译指令1.2 替换framework.ja

Android开发环境配置避坑指南

《Android开发环境配置避坑指南》本文主要介绍了Android开发环境配置过程中遇到的问题及解决方案,包括VPN注意事项、工具版本统一、Gerrit邮箱配置、Git拉取和提交代码、MergevsR... 目录网络环境:VPN 注意事项工具版本统一:android Studio & JDKGerrit的邮

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel

Python使用Matplotlib绘制3D曲面图详解

《Python使用Matplotlib绘制3D曲面图详解》:本文主要介绍Python使用Matplotlib绘制3D曲面图,在Python中,使用Matplotlib库绘制3D曲面图可以通过mpl... 目录准备工作绘制简单的 3D 曲面图绘制 3D 曲面图添加线框和透明度控制图形视角Matplotlib