第一,什么是点精灵

openGL的图形由顶点构成,以后利用顶点进行纹理的映射。点精灵就是,一个顶点被当作一个精灵来处理。特别之处就是,一个顶点也可进行纹理贴出。例如,原来是个顶点构成的一个矩形,现在一个顶点就可以完成了。瞬间我们就可以想想,粒子效果,那些云雾水流火花什么的用了点精灵,就可以瞬间减少3个顶点的计算,glDrawArrays使用GL_POINT就可以了,完全也不需要什么顶点索引了。这是非常诱人的效率。

第二,点精灵的局限

一个顶点缩放都必须是矩形。并且大小的最大最小值是有范围的,每个openGL的实现不一样需要查询获得。既然是一个纹理映射到一个顶点上,那么纹理映射就和原来完全不同,有些复杂。可能会抵消掉一些性能的优势。

第三,点精灵的使用

首先绘制的时候使用GL_POINT类型,那么在顶点着色器中就会有一个内置的只读变量可以使用,叫做gl_PointSize。这个值控制了点精灵顶点的大小,是像素数值。这个数值的范围使用如下查询:

glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, glInfo.pointSizeRange);logD("GL_ALIASED_POINT_SIZE_RANGE[%f, %f]", glInfo.pointSizeRange[0], glInfo.pointSizeRange[1]);

经过测试我发现不同的机器这个数值却别很大,有的机器有500多像素,有的只有1个像素,这确实是个问题。

接下来就是如何在这个顶点上映射纹理了。在片段着色器中仍然有一个内置的只读变量叫做gl_PointCoord。这个值是已经插值计算后的纹理坐标。就是纹理上每个像素点的xy坐标。所以这个变量是一个vec2类型的。

特别需要说明的是,纹理映射的坐标是bottom left为00点,这里是top left为00点。那么片段着色器看起来就是这样的。

gl_FragColor = texture2D(uSampler2D,gl_PointCoord);

这里以前texture2D采样的是,我们计算出来的UV值,现在这个值是默认提供的,从左上角开始的坐标。片段着色器在每个像素上执行,就会把一个默认的纹理绘制到顶点上。

第四,如何旋转,缩放,移动纹理

这里能明显感到一个问题,就是以前纹理映射到顶点上,对顶点进行矩阵运算就可以一起变化映射好的纹理了。可是现在压根就只有一个顶点,一个默认的纹理坐标如何完成操作呢。

有一点需要有一个清晰的概念。以前顶点和纹理是映射的,我们对顶点的矩阵操作就是对纹理的变换。现在需要区分开,矩阵对顶点的变换依然有效,可是对纹理没有任何作用。所以,我们需要单独对纹理进行操作,也就是对纹理坐标的变换。

方法有2种:

1,我们直接对gl_PointCoord直接操作。 这个值是一个区间在[0,1]之间的数值,代表了纹理坐标,从左上点开始。我们可以尝试的这样:

gl_FragColor = texture2D(uSampler2D, gl_PointCoord + vec2(0.5));
gl_FragColor = texture2D(uSampler2D, gl_PointCoord - vec2(0.5));

尝试一下就会发现最终点精灵上的纹理发生了偏移。但我们要把偏移,旋转,用这个坐标计算是非常麻烦的也不是不可能。但是复杂的算法放到片段着色器上,每个像素点上都运行是不明智的。

2,既然矩阵可以把各种变化一次性施加到顶点上,那么我们同样可以用矩阵来变换gl_PointCoord的坐标。这样我们可以把纹理上的像素坐标看作是顶点,顺其自然的用矩阵来变换这些顶点。只不过这些纹理顶点只有xy2个坐标,而通常我们计算顶点的矩阵是xyzw坐标。

再一次强调,纹理gl_PointCoord坐标是从top left 为00点开始。但是我们的矩阵是用00点做中心点的。这就出现一个情况,纹理矩形的几何中心点没有和矩阵的中心点重合。为了正确旋转,我们需要把纹理矩形的中心点移动到矩阵的中心点。类似如下操作

varying mat4 vTextureMat;
void main()
{                               gl_FragColor = texture2D(uSampler2D, (vTextureMat * vec4(gl_PointCoord - vec2(0.5), 0.0, 1.0)).xy + vec2(0.5));
}

这是一个片段着色器脚本。我们可以当看到,vec4构造器把纹理坐标转换到mat4可以操作的大小。gl_PointCoord – vec2(0.5)就是把纹理矩形移动到矩阵的中心点。在做矩阵操作,以后在移动回去 + vec2(0.5), 偏移0.5是为了正确使用矩阵运算。纹理坐标必须在[0,1]之间才有像素值,否则是没有像素数据的。

如此这样,我们看到了只要我们正确给出mat4 vTextureMat就能得到我们想要的一切。这个矩阵从哪里来,直接uniform传过来,或是顶点着色器varying过来都是可以的。

就像变换顶点一样,我们可以在客户端计算正确的mat4以后当纹理坐标移动,旋转,缩放。记住,这个mat4应该是和顶点变换的mvpMatrix是2个不同的矩阵。一个是为了变换顶点,一个是为了变换纹理坐标。顶点矩阵是model view projection的合体。 纹理坐标可以没有那么麻烦一个model就可以了。可以在顶点着色器计算这个矩阵,也可以在客户端算好传过来。

第五,如何在一个大图上进行UV操作,让顶点纹理是大纹理的一个部分,这样就可以BatchDraw操作了。

在顶点图形UV映射的时候,我们常常会把UV映射到大纹理上面的区域,这样我们就能搞在一个绘制中,绘制多个不同的图形了。点精灵这里只有一个顶点进行UV操作貌似没有门路。这就是问题的所在。

经过我的研究经过测试,进行UV是可以的,依然是利用矩阵来进行变换。前提是,要首先理解gl_PointCoord真正的意义所在。texture2D对顶点纹理采样的时候,是00点到11点区域进行像素处理。gl_PointCoord的范围也是[0,1]之间。那如果采样的时候,我对gl_PointCoord * vec2(0.5)进行计算会如何呢。这样就把纹理坐标映射到了[0, 0.5]之间。原来每个gl_PointCoord坐标都乘以了0.5 结果就是纹理被放大了。同理,gl_PointCoord * vec2(2.0)就会缩小纹理。

进行UV基本思路就是,把大纹理上的需要的小纹理的区域中心点,通过矩阵移动到点精灵的中心点,以后在放大区域的倍数。就会得到设置gl_PointSize大小的区域纹理,当然我们会把gl_PointSize设置的和区域纹理一样大小。这样UV的操作其实变成了矩阵的变换计算,移动,缩放就可以完成UV了。

这样做的话,UV操作用掉了矩阵缩放,点精灵的自己的缩放就要通过gl_PointSize来设置大小。还有一个问题,就是在一次性进行多个点精灵绘制的时候。针对每个点精灵都会有自己的UV坐标点,那么纹理旋转矩阵开如何是好呢,难道每个点精灵上传一个mat4矩阵么,这样的数据量太大虽然可行。我们其实还有一个选择在顶点着色器进行自己运算。

因为每个点精灵只有一个顶点,顶点着色器脚本智慧运行一次,所以在这里进行矩阵运算不会重复执行。那么旋转,缩放,平移,可能都需要去写着色器函数去实现。其实就是把cpu的计算移到显卡,我觉得速度应该更快。

最后, 点精灵有自己的局限也有效率上的优势,在研究过程中我发现点精灵可以完成square图形所有的操作。只是着色器会写的复杂一些。其中的取舍,使用的必要性,需要具体的情况去考量。
————————————————
版权声明:本文为CSDN博主「scottcgi」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tom_221x/article/details/38434627

WebGL—点精灵PointSprite详解: 纹理映射,旋转,缩放,移动相关推荐

  1. OpenGL点精灵PointSprite详解: 纹理映射,旋转,缩放,移动

    第一,什么是点精灵 openGL的图形由顶点构成,以后利用顶点进行纹理的映射.点精灵就是,一个顶点被当作一个精灵来处理.特别之处就是,一个顶点也可进行纹理贴出.例如,原来是个顶点构成的一个矩形,现在一 ...

  2. OpenGL点精灵PointSprite详解

    第一,什么是点精灵 openGL的图形由顶点构成,以后利用顶点进行纹理的映射.点精灵就是,一个顶点被当作一个精灵来处理.特别之处就是,一个顶点也可进行纹理贴出.例如,原来是个顶点构成的一个矩形,现在一 ...

  3. Three.js实例详解___旋转的精灵女孩(附完整代码和资源)(一)

    Three.js实例详解___旋转的精灵女孩(附完整代码和资源)(一) 本文目录: 一.[旋转的精灵女孩]案例运行效果 二.Three.js简介 三.Three.js代码正常运行显示条件 (1)不载入 ...

  4. Three.js实例详解___旋转的精灵女孩(附完整代码和资源)(三)

    Three.js实例详解___旋转的精灵女孩(附完整代码和资源)(三) 本篇目录: 六.完整构建整个[旋转的精灵女孩]实例 (1).新建.启动webGL工程空间 (2).构建项目的目录层次结构 (2. ...

  5. Three.js实例详解___旋转的精灵女孩(附完整代码和资源)(二)

    Three.js实例详解___旋转的精灵女孩(附完整代码和资源)(二) 本篇目录: 五.实例中所使用的代码语法详细解释 (1).构建一个三维空间场景 (2).选择一个透视投影相机作为观察点 (a).创 ...

  6. opencv warpAffine()函数详解 -- 图像旋转与平移

    简述 仿射变换是二维坐标间的线性变换,故而变换后的图像仍然具有原图的一些性质,包括"平直性"以及"平行性",常用于图像翻转(Flip).旋转(Rotations ...

  7. ffmpeg php 水平翻转,FFmpeg 视频画面旋转的命令详解及旋转失败的解决方法

    这两天在处理一段用 iPhone 拍摄的视频,在手机上看正常,导出到电脑上发现视频是倒的,或者说反的.没办法,剪辑之前必须先将它"转正".于是打算将它在 iPhone 里进行处理, ...

  8. 详解经典旋转目标检测算法RoI Transformer

    一.引言 1.旋转目标检测检测 旋转目标检测检测就是将具有旋转方向的目标检测出来,也就是需要检测目标的中心点.长宽.角度.在俯视图的目标检测中比较常见,如遥感图像目标检测.航拍图像目标检测等.(见下图 ...

  9. [Python图像处理] 三十六.OpenCV图像几何变换万字详解(平移缩放旋转、镜像仿射透视)

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

最新文章

  1. java 稀疏数组和二维数组转换,并保存稀疏数组到文件后可以读取
  2. 熟悉交换机与路由器组网(图解)
  3. SQLite的sqlite_sequence表
  4. go语言csv包_golang 写入 csv 文件
  5. G面经prepare: Pattern Match
  6. 【转】CT中的“层“与“排“的区别
  7. 循序渐进db2 第3版_「图书推荐」焊接工程师手册第3版
  8. asp之ajax技术:responstext中文乱码
  9. WPF ----在UserControl的xaml里绑定依赖属性
  10. python 外部参数过长_介绍python中slice参数过长的处理方法及实例
  11. SqlBulkCopy做大数据插入
  12. 非零矩阵A可以写成某个列满秩矩阵与某个行满秩矩阵的乘积
  13. Incapsula CDN 入门指南
  14. 达梦SQL格式化(美化器)
  15. 零件测绘与计算机作图理论试题,浅谈《零部件测绘与cad成图技术》技能竞赛对中职机械制图和cad制图课程整合的影响...
  16. 网络安全:关于Caesar密码的加密解密
  17. 客官,来看看AspNetCore的身份验证吧
  18. Lazada跨境直播,双11直播成绩傲娇!如何做到大促流量销量双收割?
  19. CSR8675模组,支持蓝牙APTX
  20. 没有人觉得B站的搜索很难用吗?— 怎么用Tableau(数据可视化)帮助饭圈女孩磕CP

热门文章

  1. 私人云储存解决方案——可道云kodexplorer【零成本】
  2. Python中break和continue区别
  3. Code Style Guide之正交设计浅析
  4. 【小松教你手游开发】【unity实用技能】u3d 层次问题总结
  5. 今夜,让我静静地想你……
  6. win10连接上OpenVpn后发现访问互联网的东西会有些不稳定
  7. ENSP华为路由器出口NAT实验
  8. 台达变频器485通讯接线图_台达变频器基本配线图
  9. 广义线性回归 logit和probit
  10. 期货账户银期转账可对接绑定哪些银行?