OpenGL 学习系列--基础的绘制流程,目前最稳定和高效的UI适配方案

这篇具有很好参考价值的文章主要介绍了OpenGL 学习系列--基础的绘制流程,目前最稳定和高效的UI适配方案。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

void main()
{
gl_FragColor = u_Color;
}

其中,gl_FragColor变量就是 OpenGL 最终渲染出来的颜色的全局变量,而u_Color就是我们定义的变量,通过在 Java 层绑定到 u_Color变量并给它赋值,就会传递到 Native 层的gl_FragColor中。

而第一行的mediump指的就是片段着色器的精度了,有三种可选,这里用中等精度就行了。uniform则表示该变量是不可变的了,也就是固定颜色了,目前显示固定颜色就好了。

编译 OpenGL 程序

明白了着色器的功能和光栅化技术之后,对渲染管线的流程也就更加清楚了,接下来就是编译 OpenGL 的程序了。

编译 OpenGL 程序基本流程如下:

  • 编译着色器
  • 创建 OpenGL 程序和着色器链接
  • 验证 OpenGL 程序
  • 确定使用 OpenGL 程序
编译着色器

创建新的文件编写着色器程序,然后再从文件以字符串的形式中读取文件内容。这样会比把着色器程序写成字符串的形式更加清晰。

当读取了着色器程序内容之后,就可以编译了。

// 编译顶点着色器
public static int compileVertexShader(String shaderCode) {
return compileShader(GL_VERTEX_SHADER, shaderCode);
}

// 编译片段着色器
public static int compleFragmentShader(String shaderCode) {
return compileShader(GL_FRAGMENT_SHADER, shaderCode);
}

// 根据类型编译着色器
private static int compileShader(int type, String shaderCode) {
// 根据不同的类型创建着色器 ID
final int shaderObjectId = glCreateShader(type);
if (shaderObjectId == 0) {
return 0;
}
// 将着色器 ID 和着色器程序内容连接
glShaderSource(shaderObjectId, shaderCode);
// 编译着色器
glCompileShader(shaderObjectId);
// 以下为验证编译结果是否失败
final int[] compileStatsu = new int[1];
glGetShaderiv(shaderObjectId, GL_COMPILE_STATUS, compileStatsu, 0);
if ((compileStatsu[0] == 0)) {
// 失败则删除
glDeleteShader(shaderObjectId);
return 0;
}
return shaderObjectId;
}

以上程序主要就是通过glCreateShader方法创建了着色器 ID,然后通过glShaderSource连接上着色器程序内容,接下来通过glCompileShader编译着色器,最后通过glGetShaderiv验证是否失败。

glGetShaderiv函数比较通用,在着色器阶段和 OpenGL 程序阶段都会通过它来验证结果。

创建 OpenGL 程序和着色器链接

接下来就是创建 OpenGL 程序并加着色器加进来。

public static int linkProgram(int vertexShaderId, int fragmentShaderId) {
// 创建 OpenGL 程序 ID
final int programObjectId = glCreateProgram();
if (programObjectId == 0) {
return 0;
}
// 链接上 顶点着色器
glAttachShader(programObjectId, vertexShaderId);
// 链接上 片段着色器
glAttachShader(programObjectId, fragmentShaderId);
// 链接着色器之后,链接 OpenGL 程序
glLinkProgram(programObjectId);
final int[] linkStatus = new int[1];
// 验证链接结果是否失败
glGetProgramiv(programObjectId, GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
// 失败则删除 OpenGL 程序
glDeleteProgram(programObjectId);
return 0;
}
return programObjectId;
}

首先通过glCreateProgram程序创建 OpenGL 程序,然后通过glAttachShader将着色器程序 ID 添加上 OpenGL 程序,接下来通过glLinkProgram链接 OpenGL 程序,最后通过glGetProgramiv来验证链接是否失败。

验证 OpenGL 程序

链接了 OpenGL 程序后,就是验证 OpenGL 是否可用。

public static boolean validateProgram(int programObjectId) {
glValidateProgram(programObjectId);
final int[] validateStatus = new int[1];
glGetProgramiv(programObjectId, GL_VALIDATE_STATUS, validateStatus, 0);
return validateStatus[0] != 0;

}

通过glValidateProgram函数验证,并再次通过glGetProgramiv函数验证是否失败。

确定使用 OpenGL 程序

当一切完成后,就是确定使用该 OpenGL 程序了。

// 创建 OpenGL 程序过程
public static int buildProgram(Context context, int vertexShaderSource, int fragmentShaderSource) {
int program;

int vertexShader = compileVertexShader(
TextResourceReader.readTextFileFromResource(context, vertexShaderSource));

int fragmentShader = compleFragmentShader(
TextResourceReader.readTextFileFromResource(context, fragmentShaderSource));

program = linkProgram(vertexShader, fragmentShader);

validateProgram(program);

return program;
}

// 创建完毕后,确定使用
mProgram = ShaderHelper.buildProgram(context, R.raw.point_vertex_shader
, R.raw.point_fragment_shader);

glUseProgram(mProgram);

将上述的过程合并起来,buildProgram函数返回的 OpenGL 程序 ID 即可,通过glUseProgram函数表示使用该 OpenGL 程序。

绘制

完成了 OpenGL 程序的编译,就是最后的绘制了,再回到渲染器 Renderer里面。

public class PointRenderer extends BaseRenderer {

private Point mPoint;
public PointRenderer(Context mContext) {
super(mContext);
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
super.onSurfaceCreated(gl, config);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// 在 onSurfaceCreated 里面初始化,否则会报线程错误
mPoint = new Point(mContext);
// 绑定相应的顶点数据
mPoint.bindData();
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// 确定视口大小
glViewport(0, 0, width, height);
}

@Override
public void onDrawFrame(GL10 gl) {
// 清屏
glClear(GL_COLOR_BUFFER_BIT);
// 绘制
mPoint.draw();
}
}

onSurfaceCreated函数里面做初始化工作,绑定数据等;在onSurfaceChanged方法里面确定视图大小,在onDrawFrame里面执行绘制。

为了简化渲染流程,把所有的操作都放在放在要渲染的对象里面去了,声明一个 Point 对象,代表要绘制的点。

public class Point extends BaseShape {

// 着色器中定义的变量,在 Java 层绑定并赋值
private static final String U_COLOR = “u_Color”;
private static final String A_POSITION = “a_Position”;
private int aColorLocation;
private int aPositionLocation;

float[] pointVertex = {
0f, 0f
};

public Point(Context context) {
super(context);
mProgram = ShaderHelper.buildProgram(context, R.raw.point_vertex_shader
, R.raw.point_fragment_shader);
glUseProgram(mProgram);
vertexArray = new VertexArray(pointVertex);
POSITION_COMPONENT_COUNT = 2;
}

@Override
public void bindData() {
//绑定值
aColorLocation = glGetUniformLocation(mProgram, U_COLOR);
aPositionLocation = glGetAttribLocation(mProgram, A_POSITION);
// 给绑定的值赋值,也就是从顶点数据那里开始读取,每次读取间隔是多少
vertexArray.setVertexAttribPointer(0, aPositionLocation, POSITION_COMPONENT_COUNT,
0);
}

@Override
public void draw() {
// 给绑定的值赋值
glUniform4f(aColorLocation, 0.0f, 0.0f, 1.0f, 1.0f);
glDrawArrays(GL_POINTS, 0, 1);
}
}

在 Point 的构造函数中,编译并使用 OpenGL 程序,而在 bindData函数中,通过glGetUniformLocationglGetAttribLocation函数绑定了我们在 OpenGL 中声明的变量u_Colora_Position,要注意的是,attribute类型和uniform类型所对应的方法是不同的,最后通过给POSITION_COMPONENT_COUNT变量赋值,指定每个顶点数据的个数为 2 。

绑定了变量之后,接下来就是给他们赋值了,对于uniform类型变量,由于是固定值,所以直接调用glUniform4f方法给其赋值就好了,而attribute类型变量,则需要对应顶点数据中的值了,vertexArray.setVertexAttribPointer方法就是完成这个任务的。

// 给某个顶点数据绑定值,并 Enable 使能
public void setVertexAttribPointer(int dataOffset, int attributeLocation, int componentCount, int stride) {
floatBuffer.position(dataOffset);
glVertexAttribPointer(attributeLocation, componentCount, GL_FLOAT, false, stride, floatBuffer);
glEnableVertexAttribArray(attributeLocation);
floatBuffer.position(0);
}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
OpenGL 学习系列--基础的绘制流程,目前最稳定和高效的UI适配方案,2024年程序员学习,学习,ui,java
OpenGL 学习系列--基础的绘制流程,目前最稳定和高效的UI适配方案,2024年程序员学习,学习,ui,java
OpenGL 学习系列--基础的绘制流程,目前最稳定和高效的UI适配方案,2024年程序员学习,学习,ui,java
OpenGL 学习系列--基础的绘制流程,目前最稳定和高效的UI适配方案,2024年程序员学习,学习,ui,java
OpenGL 学习系列--基础的绘制流程,目前最稳定和高效的UI适配方案,2024年程序员学习,学习,ui,java
OpenGL 学习系列--基础的绘制流程,目前最稳定和高效的UI适配方案,2024年程序员学习,学习,ui,java
OpenGL 学习系列--基础的绘制流程,目前最稳定和高效的UI适配方案,2024年程序员学习,学习,ui,java

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
OpenGL 学习系列--基础的绘制流程,目前最稳定和高效的UI适配方案,2024年程序员学习,学习,ui,java

总结

本文讲解了我对Android开发现状的一些看法,也许有些人会觉得我的观点不对,但我认为没有绝对的对与错,一切交给时间去证明吧!愿与各位坚守的同胞们互相学习,共同进步!

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算文章来源地址https://www.toymoban.com/news/detail-844481.html

的圈子,让我们一起学习成长!**](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

到了这里,关于OpenGL 学习系列--基础的绘制流程,目前最稳定和高效的UI适配方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • android高阶面试题,20场面试斩获大厂offer,目前最稳定和高效的UI适配方案

    美团总体的面试过程是比较顺利的,一面和二面的面试题目都回答得七七八八。而且有了前面的面试经验,此时表达更加清晰、语速也没有那么快了。在4.8号美团HR打电话通知面试通过了。但是到了此时,面试情况已经和三月20号那会不一样了。至于为什么,这还要从也是在三

    2024年04月10日
    浏览(45)
  • 加强网站稳定性!学习如何进行高效压力测试!

    1、什么是压力测试? 软件压力测试是一种基本的质量保证行为,它是每个重要软件测试工作的一部分。 软件压力测试的基本思路很简单:不是在常规条件下运行手动或自动测试,而是在计算机数量较少或系统资源匮乏的条件下运行测试。 通常要进行软件压力测试的资源包括

    2024年01月18日
    浏览(61)
  • python目前哪个版本最稳定,python什么版本比较稳定

    大家好,本文将围绕python目前哪个版本最稳定展开说明,python什么版本比较稳定是一个很多人都想弄明白的事情,想搞清楚python哪个版本好用2020需要先了解以下几个事情。 大家好,小编来为大家解答以下问题,python安装哪个版本比较好,python一般安装哪个版本,现在让我们

    2024年01月25日
    浏览(39)
  • 【OpenGL ES】三维图形绘制

    不积跬步,无以至千里;不积小流,无以成江海。要沉下心来,诗和远方的路费真的很贵! 颜色的简单搭配: 不红+不绿+不蓝 = 黑 红+绿+蓝 = 白 红+绿 = 黄 红+蓝 = 紫 绿+蓝 = 青蓝 投影主要分为 正交投影 和 透视投影 两种。 正交投影 没有近大远小的效果,是平行投影,投影

    2023年04月08日
    浏览(49)
  • 实验3—OpenGL的键盘交互绘制

    一、实验目的 1.理解OpenGL坐标系的概念,掌握OpenGL裁剪窗口、视区、显示窗口的概念和它们 之间的关系,学会计算世界坐标和屏幕坐标。 2.学会OpenGL的简单键盘交互操作。 3.学会OpenGL的简单字符绘制。 4.进一步掌握OpenGL点、直线、多边形的绘制。 二、实验内容 1.调岀实验一

    2024年04月11日
    浏览(27)
  • Selenium 学习(0.17)——软件测试之流程图绘制方法

            病假5天,出去野20天,成功错过了慕课网上的期末考试。         害,都怪玩乐太开心了……         反正咱又不指着全靠这个行当来吃饭,错过也就错过了,立的Flag能抢救一下还是要抢救一下吧。【这个其实早都会画了,而且基本也正确,既然是学习,还

    2024年02月03日
    浏览(57)
  • OpenGL ES 绘制一张图片

    GLSL 的修饰符与数据类型 GLSL 中变量的修饰符 const:修饰不可被外界改变的常量 attribute:修饰经常更改的变量,只可以在顶点着色器中使用 uniform:修饰不经常更改的变量,可用于顶点着色器和片段着色器 varying:修饰在顶点着色器计算,然后传递到片元着色器中使用的变量

    2024年02月06日
    浏览(39)
  • 使用opengl绘制茶壶并实现鼠标拖动

    难点如下:         坐标轴绘制             选定一个原点,将坐标轴正方向和反方向的俩个点进行连线,代码及效果如上图所示(本次程序中由于渲染原因,坐标轴颜色统一为棕色)         如何实现鼠标响应         OPENGL中封存有对鼠标进行相应的函数,

    2024年01月17日
    浏览(37)
  • QtOpenGL--使用OpenGL绘制曲面图(四)

    1. Qt5中的OpenGL OpenGL是用于硬件加速和3D绘图最广泛使用的图形API接口,几乎所有的桌面平台系统和大多数移动和嵌入式平台都对它提供了支持,有自己对应的实现版本。Qt库就提供了一系列方便的C++类,来帮助用户将由OpenGL支持而绘制的图形集成到自己的应用程序中。 在Qt5

    2024年02月14日
    浏览(28)
  • Android OpenGL 教程——窗口初始化&绘制矩形

    上节介绍了 Native 工程初始化,但是我们的窗口什么都没有,这节我们将 NativeActivity 创建的 window 绑定到 OpenGL 创建的 display 的 surface 上,并且绘制背景颜色和三角形,通过三角形绘制出一个矩形 初始化 绘制  只需要将三角形的索引改为6个即可 绘制 源码:OpenGLDemo#triangle 你

    2024年02月16日
    浏览(43)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包