unity3d textmesh怎么让textmesh变形

知道 Text Mesh Pro插件比Unity原生的Text组件效果好的原因了 - 推酷
知道 Text Mesh Pro插件比Unity原生的Text组件效果好的原因了
http://blog.csdn.net/u
在了解 国人开发开源的一个游戏引擎&&“
的文档时看到&&它
http://www.klayge.org/docs/klayge中的字体系统/
转载请注明出处为
,本文的永久链接为
众所周知,字体显示是所有游戏引擎都会涉及到的一个功能组件。 KlayGE 实现此功能的方式是通过点阵的形式存储和显示信息,但其呈现的字体支持一定程度上的高质量放缩,兼具了矢量图的优点。
以往的工作
目前的字体系统多种多样,从存储方式上看可分为点阵和矢量两大类。
点阵字体系统把每一个字存储成固定大小的点阵位图,常见的大小有 16&16 和 32&32 等。其中每个字形都用一组二维像素信息表示。这种文字显示方式于较早前的电脑系统(例如未有图形接口时的 DOS 操作系统)被普遍采用。常见的纯点阵字体有 bdf , pcf , fnt , hbf 等格式
。点阵字体的优点是具有简单快速的显示方式,且不受硬件限制;但是它的缺点也比较突出,即:实现高质量的放缩相对困难,特定的点阵字体只能清晰地显示在相应的字号下,否则显示的字型只能因被强行放大而失真,产生成马赛克式的锯齿边缘。因此为了满足各种显示需求,许多字体都需要要依照型号大小预先存储多套,使得字体所占的空间随着精度要求迅速上升。如果没有找到合适大小的字体,显示质量就会受到很大影响。
在矢量字体系统中,每一个字形都表示成一组数学曲线描述的轮廓,它包含了字形边界上的关键点,连线的导数信息等。在显示字体时,渲染引擎通过读取其数学矢量,并进行一定的数学运算来实现渲染,字的内部则通过光栅化来填充。矢量字体主要包括 Type1 和 TrueType 等几类
。矢量字体的优点是存储空间小,可以无限放缩而不产生变形;缺点是显示系统复杂,需要很多操作才能显示出矢量资源,因而速度较慢,也不适用于一些硬件。
随着硬件的发展, Ray 等人提出了一种新的矢量存储方式
。它把矢量图分解成许多区域,每个区域用一个多项式表示。通过把多项式的系数存在纹理中,矢量纹理就可以在 pixel shader 中很好的计算出来。这种方法解决了矢量图型在 GPU 上的渲染,但涉及较复杂的 shader ,不能适用于配置较低的硬件。
KlayGE 的字体系统设计目标是一个快速、易于实现、支持字体的高质量放缩,同时内存占用不应该太多,且适用于 DX7 以上硬件。为达到这个目的,我们选择了 “ 可放缩的点阵字体 ” 这条路线。
通过对点阵字体的分析,可以发现点阵字体不能放缩的根本原因是,点阵中每一个元素所代表的含义是 sub-pixel 的 coverage 信息
, 表示该元素所覆盖的区域有多少在字的轮廓中。举例来说,如果某个元素是 0.5 ,就表示这块区域有 50% 在字内。这样的一个 coverage 信息是非线性的,无法通过线性插值得到平滑的结果。所以强制对它进行放缩(线性插值)就会产生锯齿和间断等 artifact 。如果放弃使用 coverage 信息,而用线性的距离作为元素存储的内容,就可以在一定程度上克服放缩的麻烦。所以,我们在点阵上不存储传统的 coverage ,而存储 signeddistance field 。
经过分析,该字体系统的字形需要表示成 signed distance field 信息。做到这一点需要经过以下 4 个步骤。
第一步:生成大位图
在 KFontGen 中,这一步是通过 freetype
读取矢量字体,渲染一张
的灰度图。如下图所示(为了本文的显示方便,已经缩小到了 512&512 ,下同):
用 freetype 读取 truetype 矢量字体生成的二值化位图
第二步:轮廓搜索
freetype 生成的灰度图是经过光栅化的,也就是说字的轮廓和内部都进行了填充。我们只关心轮廓本身,所以在这一步,我们需要提取出它的轮廓,也就是同时满足
该元素的值不为 0
该元素的 8 个相邻元素存在 0
这两个条件的元素。把轮廓元素标识为 1 ,其他标示为 0 ,就可以提取到的下图所示的轮廓:
从灰度图提取轮廓
第三步:得到
distance field
一般来说,目标字体大小远远小于
。所以这里需要把对上一步得到的大位图进行离散采样,得到目标字体大小的点阵。在默认情况下, KFontGen 生成的目标字体大小是 32&32 。也就是说,从 (64, 64) 开始, x 和 y 方向分别每隔 128 采一个点。分别计算这些采样点到轮廓的最近距离,这样得到的就是一个 32&32 的 distance field 。同时,在采样的时候,根据步骤一得到的灰度图可以判断一个采样点是否在字内,如果在字内,这个距离就是正数,否则就是负数。由此可以得到所要的 signed distance field 。
第四步:量化和压缩
上一步得到的 distance field 每一个元素都是个 float 的数据,需要量化成每个元素 8 位,以减少空间占用,加速渲染。量化之后的数据经过 LZMA 压缩后存入文件中。上面例子的 distance field 经过量化可以得到一张小位图:
量化后的 signeddistance field 位图
这四个步骤原理虽然简单,但在实际实现中,需要经过比较深入的优化才能得到实用级别的速度。
二值化灰度图
步骤一得到的灰度图是存成 BYTE 的形式,每个元素一个字节。实际上我们需要的只是一个 0 , 1 的二值信息,表示一个元素是否在字内。所以我们需要对它进行二值化操作,不但节省空间,而且加速了后面的步骤。对于灰度图中的每一个元素,取它的最高位,就可以生成前述的二值化位图。注意: freetype 虽然可以直接生成单色图,但是这样生成的结果锯齿很多,无法达到高质量的要求。虽然 FT_Load_Char 可以生成字符的灰度图,但在 profile 的过程中发现 30% 的时间竟然在它的 memset 上。为了提高这个步骤的效率,应该调用的函数是 FT_Outline_Render ,通过设置 call back 来那到 freetype 的渲染结果。 freetype 的 rasterizer 会在光栅化出每一条水平线的时候调用那个 call back ,传入的是 line 的起点 x, y , length 和 coverage 。 coverage & 128 的 line 可以直接忽略,剩下的按照每个像素一个 bit 直接填入二值化位图中。这样,每个像素的开销从 memset 写入 8-bit 、 rasterizer 写入 8-bit coverage 、读取 8-bit coverage 、写入 1-bit ,简化成了 memset 写入 1-bit 、 call back 写入 1-bit , IO 减少了很多。而由于瓶颈因此从 IO 转向计算,并行性大大提高,在多核 CPU 上,处理速度可以线性地随着核的数量增长而增长。
指令加速二值化
SSE2 提供了 PMOVMSKB 指令,可以在一次提取存放在一个 XMM 中的 16 个 BYTE 的最高位,放入一个 unsigned short 中。这样能把二值化的速度提高数倍。
可以加速轮廓搜索
一旦用一个 bit 表示一个元素,就可以通过位运算来搜索轮廓。根据前面提出的轮廓条件可以推出,如果下面的表达式:
center & (center ^ (center & up & down& left & right))
不为 0 ,那么该元素在轮廓上;否则就不属于轮廓。其中 center 表示要检测的元素, up 、 down 、 left 和 right 分别表示该元素的上下左右四个相邻元素。在这里用 SSE2 可以进一步加速 and 和 xor 。
Danielsson distance transform
生成最近邻
轮廓提取的结果可以看成是一个点集,集合中每个点都在轮廓上。计算 distance field 的本质就是计算采样点到这个点集的最短距离。这个操作可以用 KD-tree 来加速
。 把点集建立成一棵 KD-tree ,然后用每个采样点的坐标去查询 KD-tree ,得到最近的轮廓点。计算它们之间的距离就可以得到该采样点到轮廓的最短距 离。但是, KD-tree 的每次搜索都是独立的, distance filed 上每个元素的搜索都没法利用到邻近元素的结果。而用 Danielsson distance transform
对目标点集做固定次数的扫描,每个点可以根据周围点的最近邻搜索结果来更新自己的信息,一次操作就可以得到所有点的最近邻。平均速度比用 KD-tree 的方法快 50% 。
经过这些优化,在 Pentium Core2 2.3GHz, 4GB DDR2-800 的机器上可以做到 174 字 / 秒的速度。
结果与比较
从恢复的结果来看, 32&32 的 signed distance field 恢复成 16&16 到 512&512 的点阵都可以得到不错的效果,边缘比较平滑,没有明显锯齿。相比之下,用 linear 方式直接放缩 32&32 的点阵,到了 128&128 的质量就严重下降了。
1. 可以通过调整 scale 在运行期无开销地改变笔划粗细:
2. 勾边很容易,只要把某一距离的像素填上特定颜色即可:
3. 给文字加上 soft shadow
总结和发展
基于 distance field 的字体能在和点阵字体存储结构相同的情况下获得更好的渲染效果,尤其是支持一定程度上的高质量放缩。由于把与矢量相关的计算挪到了预计算的部分,它的实时渲染的过程和一般点阵是一样的,远比直接渲染矢量字体来得简单。
本方法建立了矢量通往点阵的桥梁,可以很容易推广到一般矢量图的存储和渲染。任意的矢量图都可以用前述的算法转化成 signed distance field 并渲染。如果要支持彩色矢量图,可以把颜色保存在 RGB 通道, distance 保存在 A 通道。另外,还可以使用每通道 16 bit 或 32 bit 的格式,或者较大的 distance field ,以达到更高精度的要求。
在渲染 distance field 的时候,也可以使用 Marching cubes 算法
(准确地说,是它的 2D 简化版本 Marching squares
)建立出矢量图形的三角形网格。这样,渲染的时候就不再是处理点阵,而是渲染生成的三角形网格,可以利用上其他的基于三角形渲染的特效。
&Bentley, J.L.&
Multidimensional binary search trees used for associativesearching
. ACM 18, 9 (Sep. 1975), 509-517.
&ChrisGreen,&
Improved Alpha-Tested Magnification for VectorTextures and Special Effects
, GDC 2008
&Freetype. A Free,High-Quality, and Portable Font Engine.&
Intel&64 and IA-32 Architectures Software Developer’s Manuals
&Ray, N., Neiger,T., Cavin, X., and Levy, B. 2005.&
Vector texture maps on the GPU
TechnicalReport ALICE-TR-05-003
&Wikipedia,&
Computerfont
&Wikipedia,&
Marchingsquares
&William E.Lorensen, Harvey E. Cline:&
Marching Cubes: A highresolution 3D surface construction algorithm.
ComputerGraphics
,Vol. 21, Nr. 4, July 1987
&H Breu, J Gil, DKirkpatrick, M Werman.&
Linear time Euclidean distance transformalgorithms.&
IEEE Trans. Pattern Analysis and MachineIntell.&
17(5), 529-533, 1995
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致&&& 模型导入unity后,可以使用unity的Inspector面板对模型在某个坐标轴上进行平移、旋转和缩放操作(如图1)。
&&& Inspector面板提供功能是所见即所得的,调整后立刻可以看到效果,相当的方便。但是这些功能还不能完全满足游戏开发的要求,比如为了减轻美工的工作量一些游戏对场景中的模型标准作出了一些规定,使这些模块化的小模型能按照一定的规律拼接成丰富多样的大模型。拼接过程往往要对模型的local coordinates进行调整才能最终形成一个&无缝&的大模型,而这个过程常常是在游戏运行时进行(或者地图初始化时),因此需要引擎提供修改模型mesh的接口。十分幸运的是unity提供了这样的接口。
Mesh and MeshFilter
&&& 需要修改模型的网格数据,首先第一步是要想办法获得模型的mesh,这里我们需要Mesh Filter,unity文档中的解释如下:
The Mesh Filter takes a mesh from your assets and passes it to the
for rendering on the screen.
&&& 如上图,Robot手里拿的枪的网格数据保存在以gun_model命名的Mesh里,而这个Mesh则隶属于Gun_model的MeshFilter。知道了网格数据保存的位置,接下来需要做的就是获取这些数据并修改它们。下面使用一个简单的cliff模型为例子介绍如何修改模型的网格数据。
Simple Example
&&& 首先来看原始的模型长什么样?
&&& 现在需要修改模型的网格数据,把模型最高点的高度坐标挑高一倍,代码如下:
using UnityE
using System.C
[RequireComponent(typeof(MeshFilter))]
public class example : MonoBehaviour {
void Update() {
Mesh mesh = GetComponent&MeshFilter&().
Vector3 [] vertices = mesh.
int p = 0;
int flag = -1;
float maxheight = 0.0F;
while (p & vertices.Length) {
if(vertices[p].z & maxheight) {
maxheight = vertices[p].z;
vertices[flag] += new Vector3(0, 0, maxheight);
mesh.vertices =
mesh.RecalculateNormals();
&&& 注意:本例所使用的模型的local坐标系的z轴相当于unity的y轴,因此上述代码时对z轴进行修改。代码运行的结果如下:
&&& 是不是很简单!unity强大的接口以及较为详细的文档对开发者来说确实是一个福音,另外使用C#编程对于我这苦逼的不合格C++程序员来说确实很爽!
&&& 另外有一点值得注意:上述代码所对应的脚本一定要drag到GameObject里MeshFilter的拥有者,才能使代码生效。如下图5必须要把script拖拽到Cliffs01才能生效,因为在cliffs_1cm的GameObject里只有Cliffs01拥有MeshFilter(如图6)
References:
阅读(...) 评论()15207人阅读
unity3d(14)
tempQie2.transform.SetParent(GameObject.Find(&Canvas&).transform);
Text text = tempQie2.GetComponent&Text&();
text.text = contentS
text.fontSize = fontS
RectTransform rt = tempQie2.GetComponent&RectTransform&();
rt.sizeDelta = new Vector2(200, 300);
rt.transform.position = new Vector2(10, 10);
rt.transform.Rotate(new Vector3(0, 0, 45));
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:512604次
积分:4598
积分:4598
排名:第5148名
原创:76篇
转载:79篇
评论:26条
(2)(1)(1)(1)(1)(1)(1)(1)(3)(3)(1)(7)(6)(3)(4)(14)(12)(1)(1)(5)(4)(7)(2)(12)(12)(11)(4)(12)(17)(1)(1)(1)(1)(1)hudtext求教 如何才能让每个怪物单独显示自己的扣血信息?_unity3d吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:63,981贴子:
hudtext求教 如何才能让每个怪物单独显示自己的扣血信息?收藏
我目前只能实现一个怪物的扣血信息。不知道为什么,我把hud作为怪物的子物体,就会报错。所以就只能跟怪物同级。但是hud只有一个follow脚本,它可以跟随follo脚本对应的对象。但是其他对象怎么办呢?如何让每个怪物单独显示自己的扣血信息呢?求教万能的吧友。。
达内unity3d培训全程&实战教学&,unity3d专家讲师授课.免费unity3d课程试听中!到达内unity3d学院学习unity3d,只需4个月速成unity3d游戏工程师.
每生成一个怪物,都要在ui root下生成一个对应的hudtext
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或}

我要回帖

更多关于 unity3d mesh变形 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信