OpenGLES:绘制一个混色旋转的3D球体

效果展示

本博文会实现一个混色旋转的3D球体

一.球体解析

前几篇博文讲解了如何使用OpenGLES实现不同的3D图形

这一篇讲解怎样绘制3D世界的代表图形:一个混色旋转的3D球体

1.1 极限正多面体

如果看过我前几篇3D图形绘制的博文,就知道要绘制一个3D图形,首先要将3D图形拆解成可以使用单位图元——三角形进行绘制的各种子图形

然而懂点微积分的都知道,球体本身就可以看作是一个被极限分解的正多面体

所以球面可以直接使用三角形进行绘制,并不需要拆解成其他子图形

那么,现在要做的就是如何求解球体的顶点坐标。

1.2 求解球体顶点坐标

众所周知,地球上任何一个地方都能用经纬度进行标识

以此类推,先给球体设置一个经纬度

根据经纬度就将球体分解成四边形,再将四边形分解成三角形。

那么求解球体的坐标,就只需要求出四边形的坐标即可。

1.3 球体顶点坐标公式

根据上述讲解和图示,很容易就能得出球体顶点坐标公式:

  • x0 = R * cos(a) * sin(b)
  • y0 = R * sin(a))
  • z0 = R * cos(a) * cos(b)

二.GLRender:变量定义

2.1 常规变量定义

还是常见的几个变量,跟其他3D图形的常规变量并无差别

//MVP矩阵
private float[] mMVPMatrix = new float[16];//着色器程序/渲染器
private int shaderProgram;//返回属性变量的位置
//MVP变换矩阵属性
private int mvpMatrixLoc;
//位置属性
private int aPositionLocation;
//颜色属性
private int aColorLocation;//surface宽高比
private float ratio;

2.2 定义顶点坐标数组和缓冲

前文中已经讲解,对于球体,并不需要拆解出子图形,而且颜色混合我会在着色器代码中实现,并不会在Render代码中动态加载实现,因此只需要定义一个数组和缓冲,就是顶点坐标。

//球体顶点坐标数组
private float vertexData[];
//顶点缓冲
private FloatBuffer vertexBuffer;

2.3 定义MVP矩阵

//MVP矩阵
private float[] mMVPMatrix = new float[16];

三.GLRender:着色器、内存分配等

3.1 着色器创建、链接、使用

3.2 着色器属性获取、赋值

3.3 缓冲内存分配

这几个部分的代码实现2D图形绘制基本一致

可参考以前2D绘制的相关博文,里面都有详细的代码实现

不再重复展示代码

四.GLRender:动态创建顶点

创建顶点时需要传入半径:0.85f

createBallPositions(0.85f);

球体渲染的关键函数: 

createBallPositions(float r):

private void createBallPositions(float r) {// 存放顶点坐标的ArrayListArrayList<Float> alVertix = new ArrayList<Float>();// 将球进行单位切分的角度final int angleSpan = 5;// 纬度angleSpan度一份for (int wAngle = -90; wAngle < 90; wAngle = wAngle + angleSpan) {// 经度angleSpan度一份for (int jAngle = 0; jAngle <= 360; jAngle = jAngle + angleSpan) {// 纵向横向各到一个角度后计算对应的此点在球面上的坐标float x0 = (float) (r * Math.cos(Math.toRadians(wAngle)) * Math.sin(Math.toRadians(jAngle)));float y0 = (float) (r * Math.sin(Math.toRadians(wAngle)));float z0 = (float) (r * Math.cos(Math.toRadians(wAngle)) * Math.cos(Math.toRadians(jAngle)));float x1 = (float) (r * Math.cos(Math.toRadians(wAngle)) * Math.sin(Math.toRadians(jAngle + angleSpan)));float y1 = (float) (r * Math.sin(Math.toRadians(wAngle)));float z1 = (float) (r * Math.cos(Math.toRadians(wAngle)) * Math.cos(Math.toRadians(jAngle + angleSpan)));float x2 = (float) (r * Math.cos(Math.toRadians(wAngle + angleSpan)) * Math.sin(Math.toRadians(jAngle + angleSpan)));float y2 = (float) (r * Math.sin(Math.toRadians(wAngle + angleSpan)));float z2 = (float) (r * Math.cos(Math.toRadians(wAngle + angleSpan)) * Math.cos(Math.toRadians(jAngle + angleSpan)));float x3 = (float) (r * Math.cos(Math.toRadians(wAngle + angleSpan)) * Math.sin(Math.toRadians(jAngle)));float y3 = (float) (r * Math.sin(Math.toRadians(wAngle + angleSpan)));float z3 = (float) (r * Math.cos(Math.toRadians(wAngle + angleSpan)) * Math.cos(Math.toRadians(jAngle)));// 将计算出来的XYZ坐标加入存放顶点坐标的ArrayListalVertix.add(x1);alVertix.add(y1);alVertix.add(z1);alVertix.add(x0);alVertix.add(y0);alVertix.add(z0);alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);alVertix.add(x3);alVertix.add(y3);alVertix.add(z3);/*2---------------3|             / ||          /    ||       /       ||    /          || /             |1---------------0*/}}float f[] = new float[alVertix.size()];for (int i = 0; i < f.length; i++) {f[i] = alVertix.get(i);}vertexData = f;
}

五.GLRender:绘制

5.1 MVP矩阵

//MVP矩阵赋值
mMVPMatrix = TransformUtils.getBallMVPMatrix(ratio);
//将变换矩阵传入顶点渲染器
glUniformMatrix4fv(mvpMatrixLoc, 1, false, mMVPMatrix, 0);

getBallMVPMatrix(float ratio)

依然采用的是视椎体透视投影:

public static float[] getBallMVPMatrix(float ratio) {float[] modelMatrix = getIdentityMatrix(16, 0); //模型变换矩阵float[] modelMatrix0 = getIdentityMatrix(16, 0); //模型变换矩阵float[] viewMatrix = getIdentityMatrix(16, 0); //观测变换矩阵/相机矩阵float[] projectionMatrix = getIdentityMatrix(16, 0); //投影变换矩阵mBallRotateAgree = (mBallRotateAgree + 1.0f) % 360;Matrix.setRotateM(modelMatrix, 0, mBallRotateAgree, 1, 0, 1);Matrix.translateM(modelMatrix0,0,0.0f,0.3f,0.3f);Matrix.multiplyMM(modelMatrix, 0, modelMatrix, 0, modelMatrix0, 0);Matrix.setLookAtM(viewMatrix, 0, 0, 0, 3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 1, 10);float[] tmpMatrix = new float[16];float[] mvpMatrix = new float[16];Matrix.multiplyMM(tmpMatrix, 0, viewMatrix, 0, modelMatrix, 0);Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, tmpMatrix, 0);return mvpMatrix;
}

5.2 绘制球体

//准备顶点坐标内存
glVertexAttribPointer(aPositionLocation, 3, GL_FLOAT, false, 0, vertexBuffer);
//绘制
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexData.length / 3);

六.着色器代码

(1).ball_vertex_shader.glsl
#version 300 eslayout (location = 0) in vec4 vPosition;
layout (location = 1) in vec4 aColor;uniform mat4 u_Matrix;out vec4 vColor;void main() {gl_Position  = u_Matrix*vPosition;float x = vPosition.x;float y = vPosition.y;float z = vPosition.z;//效果较真实vColor = vec4(x, y, z, 0.0);
}
(2).ball_fragtment_shader.glsl
#version 300 es
#extension GL_OES_EGL_image_external_essl3 : require
precision mediump float;in vec4 vColor;out vec4 outColor;void main(){outColor = vColor;
}

八.结束语

混色旋转3D球体的绘制过程到此讲解结束了

最终实现出来的效果如同开头效果展示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/149378.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第三课 哈希表、集合、映射

文章目录 第三课 哈希表、集合、映射lc1.两数之和--简单题目描述代码展示 lc30.串联所有单词的子串--困难题目描述代码展示 lc49.字母异位分组--中等题目描述代码展示 lc874.模拟行走机器人--中等题目描述代码展示 lc146.LRU缓存--中等题目描述相关补充思路讲解代码展示图示理解…

正点原子嵌入式linux驱动开发——U-boot启动流程详解

在上一篇笔记中详细分析了uboot的顶层Makefile&#xff0c;理清了uboot的编译流程。本章来详细的分析一下uboot的启动流程&#xff0c;理清uboot是如何启动的。通过对uboot启动流程的梳理&#xff0c;可以掌握一些外设是在哪里被初始化的&#xff0c;这样当需要修改这些外设驱动…

java的内存模型(概念)

在java中&#xff0c;设计之初就有了&#xff1a;主内存、线程工作内存&#xff0c;所以其实每一个线程执行时&#xff0c;都是将主线程copy一份到工作线程&#xff0c;执行修改后&#xff0c;再同步回去。 所以&#xff0c;就有四组内存操作方式&#xff1a; 1、读主内存&…

postgresql-物化视图

postgresql-物化视图 物化视图创建物化视图刷新物化视图修改物化视图删除物化视图 物化视图 创建物化视图 postgresql使用create materialized view 语句创建视图 create materialized view if not exists name as query [with [NO] data];-- 创建一个包含员工统计信息的物化…

自学SLAM(2)---保姆教程教你如何使用自己的视频运行ORB-SLAM2

前言 如果你是新手入门&#xff0c;仅仅只会Linux的基本操作&#xff0c;并看了高翔老师视觉SLAM视屏的第一讲&#xff0c;那么你需要准备一整天的时间&#xff0c;可能还不一定能运行出来&#xff01;运行ORB-SLAM2将会安装很多很多东西。那么&#xff0c;我们准备开始&#x…

CRMEB商城源码开源标准版v5.2.0+后端+前端uni-app开源包安装教程

CRMEB打通版是一款全开源支持商用的PHP多语言商城系统,历经年时间匠心之作&#xff01;系统采用前后端分离技术&#xff0c;基于TP6Uui-app框架开发&#xff1b;客户移动端采用uni-app开发&#xff0c;管理后台前端使用iviewUI开发。系统支持微信公众号端、微信小程序端、H5端、…

C语言之自定义类型_结构体篇(1)

目录 什么是结构&#xff1f; 结构体类型的声明 常规声明 特殊声明-匿名结构体 结构体变量的定义和初始化和访问 定义 初始化 访问 嵌套结构体 结构体的自引用 什么是结构体的自引用 NO1. NO2. 热门考点&#xff1a;结构体内存对齐 产生内存对齐 NO1 NO2 …

二十九、高级IO与多路转接之epollreactor(收官!)

文章目录 一、Poll&#xff08;一&#xff09;定义&#xff08;二&#xff09;实现原理&#xff08;三&#xff09;优点&#xff08;四&#xff09;缺点 二、I/O多路转接之epoll&#xff08;一&#xff09;从网卡接收数据说起&#xff08;二&#xff09;如何知道接收了数据&…

蓝桥杯每日一题2023.9.28

AcWing 4409. 砍竹子 - AcWing 题目描述 题目分析 注&#xff1a;sqrtl的范围为long double&#xff0c;比sqrt更加精确 使用优先队列维护一段区间&#xff0c;如果连续一段相同就合并为一个区间&#xff0c;从大到小去枚举&#xff0c;每次先取出最大的一段&#xff0c;双…

专业综合课程设计 - 优阅书城项目(第一版)

此项目是《专业综合课程设计》带练项目 实现的功能有&#xff1a; 登录、注销、添加图书、删除图书、编辑图书 包含资源&#xff1a; 优阅书城&#xff08;bookstore&#xff09;源码 数据库数据 课程笔记 下载链接&#xff1a;https://wwpv.lanzoue.com/i79nx1av4doj 登录功…

windows系统服务管理命令sc

sc可以用于管理系统服务、计划任务、系统日志等方面&#xff0c;是不可或缺的神器。 基本用法 在命令提示符下输入sc命令&#xff0c;然后按回车键。 上图展示的是sc命令的使用方法&#xff0c;支持哪些参数实现哪些功能 要查看系统所有服务列表&#xff0c;包括它们是否正在…

逻辑回归评分卡

文章目录 一、基础知识点(1)逻辑回归表达式(2)sigmoid函数的导数损失函数(Cross-entropy, 交叉熵损失函数)交叉熵求导准确率计算评估指标 二、导入库和数据集导入库读取数据 三、分析与训练四、模型评价ROC曲线KS值再做特征筛选生成报告 五、行为评分卡模型表现总结 一、基础知…

Go-Python-Java-C-LeetCode高分解法-第八周合集

前言 本题解Go语言部分基于 LeetCode-Go 其他部分基于本人实践学习 个人题解GitHub连接&#xff1a;LeetCode-Go-Python-Java-C 欢迎订阅CSDN专栏&#xff0c;每日一题&#xff0c;和博主一起进步 LeetCode专栏 我搜集到了50道精选题&#xff0c;适合速成概览大部分常用算法 突…

2023年-华为机试题库B卷(Python)【满分】

1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣ 8️⃣ 9️⃣ &#x1f51f; 华为机试题库B卷 已于5月10号 更新为2023 B卷 &#xff08;2023-10-04 更新本文&#xff09; 华为机试有三道题目&#xff0c;前两道属于简单或中等题&#xff0c;分值为100分&#xff0c;第三道为中等或…

互动营销类游戏开发小程序游戏开发

互动营销类游戏开发是一种创意和有趣的方式&#xff0c;可以用于推广产品、品牌或服务。这些游戏旨在吸引玩家并与他们互动&#xff0c;以促使他们与您的品牌建立更紧密的联系。 当今数字时代的市场竞争激烈&#xff0c;品牌和企业需要采用创新的方法来吸引并保持用户的兴趣。…

MySQL基础-事务

目录 1.事务简介 2.事务的操作 2.1 实验需要用到的数据 2.2 完成转账操作 修改事务执行方式 手动开启事务的方式 3.事务的四大特性 4.并发事务问题 5.事务隔离级别 5.1 事务隔离级别分类 5.2 查看事务隔离级别 5.3 设置事务隔离级别 1.事务简介 事务是一组操作的集合…

实时人脸五观检测:基于libfacedetection(CNN模型)

一、前言 随着人工智能技术的不断发展,人脸检测已成为计算机视觉领域的重要应用之一。人脸检测是一种将输入图像中的人脸位置和轮廓提取出来的技术,广泛应用于人脸识别、智能监控、人机交互等领域。利用libfacedetection开源的人脸检测库,实现人脸检测。 libfacedetection…

第一课数组、链表、栈、队列

第一课数组、链表、栈、队列 acwing136 邻值查找---中等题目描述代码展示 lc20.有效的括号--简单题目描述代码展示 lc25.K 个一组翻转链表--困难题目描述代码展示 lc26.删除有序数组中的重复项--简单题目描述代码展示 lc88.合并两个有序数组--简单题目描述代码展示 lc141.环形链…

mysql-binlog

1. 常用的binlog日志操作命令 1. 查看bin-log是否开启 show variables like log_%;2. 查看所有binlog日志列表 show master logs;3.查看master状态 show master status;4. 重置&#xff08;清空&#xff09;所有binlog日志 reset master;2. 查看binlog日志内容 1、使用mysqlb…

目前制造企业生产计划现状是什么?有没有自动化排产系统?

大家都知道&#xff0c;人的指挥中心是大脑&#xff0c;大脑对我们的发出各种各样的指令&#xff0c;告诉我们&#xff1a;“手”做什么事情&#xff0c;“眼睛”看什么地方&#xff0c;“耳朵”听什么声音&#xff0c;然后再将摸到的、看到的、听到的信息传递给大脑&#xff0…