第一,什么是点精灵

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过来都是能够的。

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

第五,怎样在一个大图上进行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图形全部的操作。仅仅是着色器会写的复杂一些。当中的取舍,使用的必要性,须要详细的情况去考量。

openGL点精灵PointSprite具体解释: 纹理映射,旋转,缩放,移动的更多相关文章

  1. 【OpenGL(SharpGL)】支持任意相机可平移缩放的轨迹球实现

    [OpenGL(SharpGL)]支持任意相机可平移缩放的轨迹球 (本文PDF版在这里.) 在3D程序中,轨迹球(ArcBall)可以让你只用鼠标来控制模型(旋转),便于观察.在这里(http://w ...

  2. osg矩阵变换节点-----平移旋转缩放

    osg矩阵变换节点-----平移旋转缩放 转自:http://www.cnblogs.com/ylwn817/articles/1973396.html 平移旋转缩放这个三个是osg矩阵操作中,最常见 ...

  3. osg中使用MatrixTransform来实现模型的平移/旋转/缩放

    osg中使用MatrixTransform来实现模型的平移/旋转/缩放 转自:http://www.cnblogs.com/kekec/archive/2011/08/15/2139893.html# ...

  4. Blender模型导入进Unity,旋转缩放的调整

    Blender跟Unity的XYZ轴不同的原因,导致Blender模型导入Unity之后会发生模型朝向不对. 请先看看下边这个情况: 首先,Blender物体模式下,对模型进行 旋转 缩放,将会在右边 ...

  5. NeHe OpenGL教程 第六课:纹理映射

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  6. OpenGL 4.0 GLSL 实现 投影纹理映射(Projective Texture Mapping) (转)

    http://blog.csdn.net/zhuyingqingfen/article/details/19331721   分类: GLSL  投影纹理映射 (projective texture ...

  7. OpenGL绘制简单场景,实现旋转缩放平移和灯光效果

    本项目实现了用OpenGL绘制一个简单场景,包括正方体.球体和网格,实现了物体的旋转.缩放.平移和灯光效果.附有项目完整代码.有具体凝视.适合刚開始学习的人熟悉opengl使用. 开发情况 开发环境V ...

  8. 【Android 应用开发】OpenGL ES 2.0 -- 制作 3D 彩色旋转三角形 - 顶点着色器 片元着色器 使用详解

    最近开始关注OpenGL ES 2.0 这是真正意义上的理解的第一个3D程序 , 从零开始学习 . 案例下载地址 : http://download.csdn.net/detail/han120201 ...

  9. OpenGL ES: iOS 自定义 UIView 响应屏幕旋转

    iOS下使用OpenGL 如果使用GLKit View 那么不用担心屏幕旋转的问题,说明如下: If you change the size, scale factor, or drawable pr ...

随机推荐

  1. QT操作Excel(通过QAxObject使用了OLE,前提是本地安装了Excel)

    新建QT GUI项目,在选择选项中勾选ActiveQT Container. #include <qaxobject.h> QAxObject *obj = new QAxObject(& ...

  2. NetAnalyzer2016使用方法

    NetAnalyzer笔记 之 八 NetAnalyzer2016使用方法(2)   [创建时间:2016-05-06 22:07:00] NetAnalyzer下载地址 在写本篇的时候,NetAna ...

  3. HBase总结(二十)HBase经常使用shell命令具体说明

    进入hbase shell console $HBASE_HOME/bin/hbase shell 假设有kerberos认证,须要事先使用对应的keytab进行一下认证(使用kinit命令),认证成 ...

  4. Android内存管理

    首先Android理机制相当复杂.想要讲清楚比較困难.其次对于绝大多数用户来说.仅仅关心内存够不够用,至于内存怎样管理的这样的技术细节,不是用户须要去考虑的,写这样一个专题有没有意义?毕竟我们是用手机 ...

  5. POJ 2778 AC自己主动机+矩阵幂 不错的题

    http://poj.org/problem?id=2778 有空再又一次做下,对状态图的理解非常重要 题解: http://blog.csdn.net/morgan_xww/article/deta ...

  6. ffplay2 android 版正式公布

    项目地址:https://github.com/DeYangLiu/AndroidPlayer/ 下载链接: 看点: 支持软键盘输入和历史记录.使用了EditText和内部存储. 这里考虑了历史记录的 ...

  7. mysql导出和导入数据库

    出口 在dos计划,切换到mysql按照该文件夹bin下一个.输入以下命令 mysqldump -u root -p nxu_life > nxu_life2.sql 运行完毕后,就能够看到在b ...

  8. hdu3062(two-sat)

    传送门:Party 题意:有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席.在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在 ...

  9. 实现ListView A~Z快速索引

    ListView A~Z快速索引这种效果在通信录和城市列表中经常看到,方便用户查找,是一种增加用户体验的好方法. 实现步骤: 1.自定义一个名叫SlideBar 的View. 2.在布局文件中加入这个 ...

  10. HDU 5071 Chat

    题意: CLJ找了很多妹子-  (题目好没节操-)  对于CLJ和妹子的聊天对话框  有一下几种操作: add  加一个妹子在聊天窗队列末尾  假设这个妹子已经在队列中则add失败 close  关掉 ...