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 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

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

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

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

Ollama整合open-webui的步骤及访问

《Ollama整合open-webui的步骤及访问》:本文主要介绍如何通过源码方式安装OpenWebUI,并详细说明了安装步骤、环境要求以及第一次使用时的账号注册和模型选择过程,需要的朋友可以参考... 目录安装环境要求步骤访问选择PjrIUE模型开始对话总结 安装官方安装地址:https://docs.

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超