接着前一篇《WebGL实现sprite精灵效果的GUI控件》,我们继续开发我们的数字系统GUI控件,因为这套数字系统是基于sprite效果的,所以数字随相机转动而旋转(永远面对相机),随场景缩放而逆向缩放(数字在屏幕上看上去大小不变)。实现sprite效果的核心方法在前一篇文章里已经详细说明,这里不再赘述,本文要讨论的是如何将用户输入的数字文本转变成GUI控件的数字贴图。请看demo。

我们能清楚地看到,在角度测量模式下,我们动态地绘制了两条边的长度数字贴图和角度大小的数字贴图。对于我们来说,计算边长和夹角是非常简单的工作,但怎么把结果数字转变成对应的图片呢,这里鲫鱼是通过uv坐标和数字图片一一映射实现的。其实原理非常简单,鲫鱼有一张包含0~9和小数点,角度的°的图片png,用户输入是一串包含0~9,小数点和°的字符串,鲫鱼将每一个字符都绑定图片的uv坐标,这样构造出的函数输入是字符串,返回就是对应输入字符串的uv坐标数组。我们知道构造纹理texture的贴图就是利用图片的uv坐标来定位图片在texture上的位置信息,利用这个原理,鲫鱼拿回的uv数组就完成了将一个一个数字贴到一片显式数字的矩形模型中,用户看到的就会是一片显式一串数字的矩形(当然矩形是透明的,用户只能看到数字)。

  以上是原理的解释,我们先来看一下数字的png图片长啥样。

这张就是包含数字和小数点和°的png图片,注意它是正方形的,且尺寸是2的幂次方。这两点前者是为了优化webgl的材质渲染,后者是为了能被webgl的材质所识别。为了做成正方形,我们用空白填充。好了,接下来我们来看看代码,关于uv贴图的映射和texture绑定图片,我们先来看uv映射。

  1 /**
  2  * 字库
  3  * */
  4 let TextImage = function(){
  5     this._library = {
  6         ZERO_UV:[0, 1, 0, 0.75, 0.25, 1, 0.25, 0.75],
  7         ONE_UV:[0, 0.75, 0, 0.5, 0.25, 0.75, 0.25, 0.5],
  8         TWO_UV:[0, 0.5, 0, 0.25, 0.25, 0.5, 0.25, 0.25],
  9         THREE_UV:[0, 0.25, 0, 0, 0.25, 0.25, 0.25, 0],
 10         FOUR_UV:[0.25, 1, 0.25, 0.75, 0.5, 1, 0.5, 0.75],
 11         FIVE_UV:[0.25, 0.75, 0.25, 0.5, 0.5, 0.75, 0.5, 0.5],
 12         SIX_UV:[0.25, 0.5, 0.25, 0.25, 0.5, 0.5, 0.5, 0.25],
 13         SEVEN_UV:[0.25, 0.25, 0.25, 0, 0.5, 0.25, 0.5, 0],
 14         EIGHT_UV:[0.5, 1, 0.5, 0.75, 0.75, 1, 0.75, 0.75],
 15         NINE_UV:[0.5, 0.75, 0.5, 0.5, 0.75, 0.75, 0.75, 0.5],
 16         DOT_UV:[0.5, 0.5, 0.5, 0.25, 0.75, 0.5, 0.75, 0.25],
 17         DEGREE_UV:[0.5, 0.25, 0.5, 0, 0.75, 0.25, 0.75, 0]
 18     };
 19 };
 20
 21 TextImage.prototype.constructor = TextImage;
 22 TextImage.prototype = {
 23
 24     /**
 25      * 通过输入文字返回图片,小数点后保留3位
 26      * text:输入的文字
 27      * */
 28     getImagesByText:function(text){
 29         text = this.changeUnit(0.001, text);
 30         text = this.keepEffectNum(3, text);
 31         text = text.toString();
 32         //逐字符匹配图片
 33         let imgUVs = [];
 34         for(let i=0; i<text.length; i++){
 35             let imgUV = this.match(text[i]);
 36             imgUVs = imgUVs.concat(imgUV);
 37         }
 38         return imgUVs;
 39     },
 40
 41     /**
 42      * 通过输入角度返回图片,小数点后保留3位
 43      * angle:输入的文字
 44      * */
 45     getAngleImagesByText:function(angle){
 46         angle = this.keepEffectNum(3, angle);
 47         angle = angle.toString();
 48         angle = angle + "#";
 49         //逐字符匹配图片
 50         let imgUVs = [];
 51         for(let i=0; i<angle.length; i++){
 52             let imgUV = this.match(angle[i]);
 53             imgUVs = imgUVs.concat(imgUV);
 54         }
 55         return imgUVs;
 56     },
 57
 58     /**
 59      * 单位换算
 60      * ratio:换算率
 61      * text:输入的值
 62      * */
 63     changeUnit:function(ratio, text){
 64         return ratio * text;
 65     },
 66
 67     /**
 68      * 小数点后保存n位
 69      * effect:有效数字
 70      * text:原始数字
 71      * */
 72     keepEffectNum:function(effect, text){
 73         return text.toFixed(effect);
 74     },
 75
 76     /**
 77      * 匹配字符和图片
 78      * char:字符
 79      * */
 80     match:function(char){
 81         let imgUV = undefined;
 82         if(char === "0"){
 83             imgUV = this._library.ZERO_UV;
 84         }else if(char === "1"){
 85             imgUV = this._library.ONE_UV;
 86         }else if(char === "2"){
 87             imgUV = this._library.TWO_UV;
 88         }else if(char === "3"){
 89             imgUV = this._library.THREE_UV;
 90         }else if(char === "4"){
 91             imgUV = this._library.FOUR_UV;
 92         }else if(char === "5"){
 93             imgUV = this._library.FIVE_UV;
 94         }else if(char === "6"){
 95             imgUV = this._library.SIX_UV;
 96         }else if(char === "7"){
 97             imgUV = this._library.SEVEN_UV;
 98         }else if(char === "8"){
 99             imgUV = this._library.EIGHT_UV;
100         }else if(char === "9"){
101             imgUV = this._library.NINE_UV;
102         }else if(char === "."){
103             imgUV = this._library.DOT_UV;
104         }else if(char === "#"){
105             imgUV = this._library.DEGREE_UV;
106         }
107         return imgUV;
108     }
109 };
110
111 module.exports = TextImage;

  我们看到这个TextImage类拥有一个this._library字库,其中每一个数字都绑定了一串uv坐标,即图片中每一个数字的左上角->左下角->右下角->右上角逆时针绕向的4组坐标值。在match函数中通过函数输入参数的字符来返回对应的uv坐标数组。这就是数字绑定uv的原理。再来看我们拿到uv数组怎么绑定到材质对象中去。请看下面代码。

 1 /**
 2      * 创建几何
 3      * viewer:视图对像
 4      * textNode:文字节点
 5      * width:宽
 6      * height:高
 7      * position:位置坐标
 8      * imgUVs:图片uv数组
 9      * texture:数字纹理
10      * */
11     addGeometry:function(viewer, textNode, width, height, position, imgUVs, texture){
12         //顶点缓存
13         let w = width;
14         let h = height;
15         //缩放比
16         let scaleRatio = 1;
17         scaleRatio = this.againstScale(position, viewer);
18         w = w*scaleRatio;
19         h = h*scaleRatio;
20         //顶点数组
21         let vertices = [];
22         //首先确定有几张图片
23         let imgNum = imgUVs.length/8;
24         if(imgNum !== 0){
25             for(let i=0; i<imgNum; i++){
26                 vertices.push(w*i, h, 0, w*i, 0, 0, w*(i+1), h, 0, w*(i+1), 0, 0);
27             }
28         }
29         let array = new Float32Array(vertices);
30         let vertexBuffer = new BufferArray(BufferArray.ARRAY_BUFFER, array, 3);
31         //索引缓存
32         let indices = [];
33         if(imgNum !== 0){
34             for(let i=0; i<imgNum; i++){
35                 indices.push(4*i, 4*i+1, 4*i+3, 4*i+3, 4*i+2, 4*i);
36             }
37         }
38         let index = new Int8Array(indices);
39         let indexBuffer = new BufferArray(BufferArray.ELEMENT_ARRAY_BUFFER, index, index.length);
40         //绘制图元
41         let prim = new DrawElements(Primitives.TRIANGLES, indexBuffer);
42         //几何对象
43         let geom = new Geometry();
44         geom.setBufferArray('Vertex', vertexBuffer);
45         geom.setPrimitive(prim);
46         //纹理坐标
47         let uv = new Float32Array(imgUVs);
48         let uvBuffer = new BufferArray(BufferArray.ARRAY_BUFFER, uv, 2);
49         geom.setBufferArray('Texture', uvBuffer);
50         //将texture加入geometry
51         geom.getStateSet(true).addAttribute(texture, StateAttribute.OVERRIDE);
52         //图片背景透明
53         let bf = new BlendFunc(BlendFunc.SRC_ALPHA, BlendFunc.ONE_MINUS_SRC_ALPHA);
54         geom.getStateSet(true).addAttribute(bf, StateAttribute.OVERRIDE);
55         //几何对象加入根节点
56         textNode.addChild(geom);
57         //将textNode的位置平移到position位置
58         let translateMat = Mat4.MemoryPool.alloc();
59         Mat4.fromTranslation(translateMat, position);
60         Mat4.copy(textNode._matrix, translateMat);
61         //根据主相机视口调整模型旋转,保证文字总是面向相机
62         this.computeMatrix4MainCamera(textNode._matrix, viewer);
63         //析构
64         Mat4.MemoryPool.free(translateMat);
65     },

我们看到,我们的uv转成BufferArray后被geometry对象所接收,let uv = new Float32Array(imgUVs); let uvBuffer = new BufferArray(BufferArray.ARRAY_BUFFER, uv, 2); geom.setBufferArray('Texture', uvBuffer);通过这三行代码,我们的几何体对象里就包含了材质信息,鲫鱼接下来很欢快地发现,数字贴图完整地绘制到模型节点中去了。
  以上就是对数字GUI组建的完整说明,谢谢同学们的关注与支持,鲫鱼和大家一起进步,鲫鱼和同学们下周再见。

  本文系原创,如需引用,请注明出处:https://www.cnblogs.com/ccentry/p/10322832.html

转载于:https://www.cnblogs.com/ccentry/p/10322832.html

WebGL之sprite精灵效果显式数字贴图相关推荐

  1. CML 2020 | 显式引入对分类标签的描述,如何提高文本分类的效果?

    论文链接:https://arxiv.org/pdf/2002.03067.pdf 1 简介 一般来说,模型越深效果越好.但是同时,模型越深也更难训练--即无法收敛到训练集上一个好的值. 今天,我们给 ...

  2. hssfcell判断文本类型_ICML 2020 | 显式引入对分类标签的描述,如何提高文本分类的效果?...

    本文介绍的是ICML2020论文<Description Based Text Classification with Reinforcement Learning>,论文作者来自香侬科技 ...

  3. 伊莱科多功能数显式仪器仪表EM33D袖珍高精度全自动表笔电工数字万能表

    伊莱科多功能数显式仪器仪表EM33D袖珍高精度全自动表笔电工数字万能表https://buy.icxbk.com/h5/pages/product/detail?pid=3534

  4. 斯坦福马腾宇:用显式正则器提升深度神经网络的泛化能力

    2019年12月30日,在"智源论坛·海外学者学术报告会"上,斯坦福大学计算机科学和统计学助理教授马腾宇博士做了<为深度模型设计显式正则器>的主题演讲.马腾宇,本科就读 ...

  5. 【生成模型】解读显式生成模型之完全可见置信网络FVBN

    上一期为大家说明了什么是极大似然法,以及如何使用极大似然法搭建生成模型,本期将为大家介绍第一个显式生成模型完全可见置信网络FVBN. 作者&编辑 | 小米粥 1 完全可见置信网络 在完全可见置 ...

  6. 论文浅尝 - ACL2020 | 利用常识知识图对会话流进行显式建模

    笔记整理 | 韩振峰,天津大学硕士 链接:https://arxiv.org/pdf/1911.02707.pdf 动机 人类对话自然地围绕相关概念发展,并分散到多跳概念.本文提出了一种新的会话生成模 ...

  7. 论文浅尝 | 机器阅读理解中常识知识的显式利用

    论文笔记整理:吴林娟,天津大学硕士,自然语言处理方向. 链接:https://arxiv.org/pdf/1809.03449.pdf 动机 机器阅读理解(MRC)和人类进行阅读理解之间还存在差距,作 ...

  8. 显式锁Lock的集大成之作,最细节教程

    显式锁是什么? 我们一般喊synchronized就叫synchronized.其实synchronized又被称为隐式锁,但我们就爱喊它synchronized.而显式锁就是我们一般说的Lock锁, ...

  9. 保持显式用户参与的有效自动化创建

    摘  要: 在日益复杂的环境中,如汽车驾驶,用户失去对自动化的参与会产生越来越多意想不到的后果.本文提出了一个用于在现有系统中进行协同自动化设计的三步流程,以在维持用户参与的限制下最大化系统性能.第一 ...

最新文章

  1. 与HTTP关系密切的协议:IP、TCP、DNS
  2. ecshop的smarty库还原成smarty原生库方法
  3. elementUI vxe-table结合使用(通用表格)
  4. CUDA层硬件debug之路
  5. java tostring方法_Java虚拟机如执行方法调用的(二)?
  6. 抽象类的有参与无参构造函数的研究
  7. individual program总结2.0
  8. Windows 10中无需禁用强制驱动签名检测加载驱动
  9. 广西(柳州)创建国家级车联网先导区建设方案
  10. 微波存在感应雷达,人体存在感应雷达模块,物联网智能赋能应用
  11. 计算机主机进水无法启动,笔记本电脑进水后出现不能正常开机启动
  12. Silverlight新型的富媒体
  13. EOS区块链一周要闻回顾(2.24-3.01)
  14. 达人评测 i7 12700H和R7 6800H选哪个好
  15. C#实现土豆优酷等网站视频的缩略图
  16. HTML表格,列表,超链接,图片
  17. error: %preun(mysql-community-server-5.7.36-1.el6.x86_64) scriptlet failed
  18. Verilog数字系统设计——8位数字比较器
  19. STM32读取SHT3x系列温湿度传感器,标准库和HAL库
  20. 优秀,好用,一年使用经验推荐给你几款优秀的程序员一定要知道的画图工具

热门文章

  1. 使用密钥验证方式登录linux系统
  2. 分享在winform下实现左右布局多窗口界面
  3. $\LaTeX$笔记:Section 编号方式(数字、字母、罗马)计数器计数形式修改
  4. javascript去除首尾空白字符
  5. 软件包有未满足的依赖关系
  6. ASP.NET MVC 3 Razor 多国语言参考解决方案 补充四
  7. VISP视觉库识别AprilTag详细解读
  8. c 初始化char**_CC++|指针详述及实例分析
  9. rabbitmq实战:高效部署分布式消息队列_一文看懂消息队列中间件--AMQ及部署介绍...
  10. [JUC-5]ConcurrentHashMap源码分析JDK8