Posts

使用VS2005编译freetype的动态链接库

使用VS2005编译freetype的动态链接库 请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 使用freetype是2.3.8版本,freetype2.3.8包解压缩后,在**.\builds\win32\visualc**目录下有基于vs2005的sln文件,不过这个解决方案文件,只是包含有生成静态链接的工程设置,要编译动态链接库,还需要手动去处理一下。步骤如下: 参考./doc目录下的INSTALL.ANY文档。该文档其实已经把标准编译所要包含的文件及它们的作用说得很清楚了,现在使用VC2005建立一个空的win32DLL工程,然后按照INSTALL.ANY的说明把需要加入的文件加入工程内,INSTALL.ANY文件内有一很明显的提醒:“DO NOT COMPILE ALL C FILES!”,就是不要编译所有的C文件,这点应该注意。 要进行修改的文件是ftoption.h,该文件在**/include/freetype/config**目录下,该目录主要存放一些配置头文件。ftoption.h文件里对每一可定制项目都有很详细的解释,为了可以编译成DLL,要进行的修改是: 首先备份一下ftoption.h,如,另存为ftoption_bak.h文件。 根据ftoption.h在 “DLL export compilation” 项里的描述,FreeType2库在需要导出的函数前都使用了FT_EXPORT(用在函数定义处),FT_EXPORT_DEF(用在函数声明处)两个宏,需要重新定义这两个宏。FreeType2库对于FT_EXPORT和FT_EXPORT_DEF宏的缺省定义在ftconfig.h文件中。所以在ftopion.h的该处重新定义自己的FT_EXPORT和FT_EXPORT_DEF就可以了,重新定义如下所示: #ifdef FT2_DLL //因为在静态库与动态中都使用该文件,所以区别使用该指示字,使用FT2_DLL表示要编译为DLL动态库。 #ifdef FT2_EXPORTS //按照微软的标准做法,定义__declspec(dllexport)与__declspec(dllimport) #define FT_EXPORT( x ) __declspec(dllexport) x #define FT_EXPORT_DEF( x ) x #else //按照微软的说法,其它__declspec(dllimport)也可以不要的,但这样做,更有效率并且如果不这么做的话有时会出现问题 #define FT_EXPORT( x ) __declspec(dllimport) x #define FT_EXPORT_DEF( x ) x #endif #endif

Unity3D的碰撞检测响应处理细节

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 1 对碰撞做出响应所必须的条件 要想两个物体A,B发生碰撞检测,即触发OnCollision相关事件,或者触发OnTrigger相关事件。必须: 物体A,B都挂接上了一个碰撞器组件,即Collider类(2D环境下是Collider2D类)的子类 运动着的物体,要携带一个刚体组件,即RigidBody类(2D环境下是RigidBody2D类),另一方的物体如果是静止的话,可以不用携带刚体组件。 2 碰撞时触发OnCollision相关事件的条件 在满足第1节中所提出的条件下,当两者的刚体组件(如果有的话)的Is Kinematic属性都未勾选,且两者的碰撞器组件的Is Trigger属性,都没勾选时,便会触发OnCollision相关事件。 3 碰撞时触发OnCollision相关事件的条件 在满足第1节中所提出的条件下,当两者的碰撞器组件的Is Trigger属性,其中有一个勾选时,就会触发OnTrigger相关事件。 4 响应事件的分类 响应事件分为Enter、Stay、Exit。以OnTrigger为例,就是OnTriggerEnter、OnTriggerStay、OnTriggerExit(2D环境下就是OnTriggerEnter2D,OnTriggerStay2D,OnTriggerExit2D,OnCollision事件以此类推)。 Enter事件便是两个物体碰撞的那一瞬间,此事件在碰撞过程会执行一次 Stay事件表示两个物体在持续接触时,此事件在碰撞过程会多次执行。 Exit事件便是两个物体在分开的那一瞬间,此事件在碰撞过程会执行一次

解决Unity3D在编译时出现libpng iccp警告的问题

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 项目组使用Unity3D4.6进行渠道商SDK接入,在编译Android版本时,发现部分渠道商提供的SDK包在编译时会出现如下图的问题: 经查证,新版本的Unity3D采用了较高版本的libpng库作为png格式图片的处理模块,产生此问题的原因是新版本的libpng对png的ICCP采用了更严格的约束条件,因此,我们必须使用软件对渠道商提供的这些资源png图片进行处理,以解决这个问题。开源软件 ImageMagick 提供了处理这个问题的方案。 从ImageMagick网站下载了ImageMagick Display软件包,安装后如下图: 我们使用软件包中的convert.exe程序对这些图片进行处理。convert程序是一个命令行程序,该程序有很多开关参数。我们使用-strip参数处理。命令行格式为: convert 待处理的图片的文件名 -strip 处理后输出的图片文件名 如果需要一口气处理同一文件夹下的许多png,我们可以将处理命令写成一个批处理文件,代码如下: set fn=E:\software\ImageMagick-6.9.0-Q16\convert.exe for /f "tokens=*" %%i in ('dir/s/b *.png') do "%fn%" "%%i" -strip "%%i"

在Unity3D中模型渲染时边缘抖动有杂点的问题解决方案

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 项目主美反映了一个问题,即在U3D中,给模型使用了镜面高光的材质,结果模型的边缘有很多白色的杂点,如果换用了普通漫反射材质的话,杂点的明显稍微没那么强烈,如下图,左边是使用了镜面高光材质,右边是使用了漫反射材质。 一开始,我以为是因为模型的Z-fighting问题,即两个带纹理的模型因为太靠近了,导致因渲染时的精度问题而造成模型的穿插。但后来检查了模型,并不存在“靴子里面还套着小腿”的这种情况。所以不是Z-fighting的问题。 后来google了一下,发现老外们也曾经发现过类似的问题。最终有人提出这是一个因为抗锯齿做得不好的问题,解决方案就是给摄像机加一个基于image post process机制的脚本AntialiasingAsPostEffect,然后选用FXAA反走样的着色器。加入之后,效果不错,杂点问题得到了较为明显的改善。 KlayGE引擎开发者,大神龚敏敏认为基于post process处理的技术目前已经是逐渐成为主流。nVidia等公司有很多大牛也提出了不少的算法。比如FXAA算法就是由nVidia的研究员Timothy Lottes提出的算法。所以可以预见不远的将来这项技术会逐渐普及。但目前因为硬件能力的问题,在手机移动平台上,依然要注意使用这种算法的性能问题。

Unity3D烘焙光照图在移动平台上颜色失真的分析和应对方案

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com Unity烘焙的LightMap是32bit的HDR图,而移动设备通常不支持 HDR图(32bit per channel) ,会按照 LDR图(8bit per channel) 的形式进行处理,因此会出现色偏问题。即颜色变淡,在例子中地面为绿色,因此相比于PC平台,切到移动平台如Android或者iOS上之后,黄色变淡,使得地面的绿色更加显眼。对此Unity3D技术支持人员的的建议是: 可尝试自行修改LightMap的DecodeLightmap函数,该函数可在 Unity\Editor\Data\CGIncludes\UnityCG.cginc 文件中找到。需要说明的是,这种方法也不能达到与PC端完全一致的效果。 为了避免类似问题,请不要使用过于强烈的Light进行烘焙,因为Light的强度(Intensity)越高,色偏问题会越严重。

Unity3D的渲染路径的细节一览表

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 1 功能列表 功能 Vertex Lit Rendering Path Forward Rendering Path Deferred Rendering Path 逐像素光照效果(Normal map等) N Y Y 多render pass支持 仅在一个render pass中完成光照计算 允许多render pass 允许多render pass 逐像素实时阴影 N 仅支持一盏Directional Light Y 双光照贴图(Dual Lightmaps) N N Y 深度缓冲区和法线缓冲区 N Additional Render Pass Y 软粒子(soft particle) N N Y 半透明的物体(Semitransparent objects) N Y Y 反走样(抗锯齿 anti aliasing) N Y Y 灯光剔除蒙版(Lighting Culling masks) 受限制 Y Y 光照保真度(Lighting Fidelity) 所有光照计算在顶点着色器中执行 部分光照计算在片元着色器中执行 所有光照计算在片元着色器中执行 每像素光照的性能耗费 像素数 像素数*被实时光照亮的像素数 PC上的所需的最低shader model版本 任意版本 最低2.

移动GPU技术参数术语整理一览表

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 术语 解释 IMR Immediate Mode Rendering 立即渲染模式 TBR Tile Based Rendering 分块渲染模式。该模式架构在把三角形场景变成像素图(光栅化)前,先把整个画面分成小块,这些小块的渲染在GPU上的高速缓存里进行,这样就避免了对帧缓存(位于系统内存里)的频繁读写和修改。当然,由于一个三角形可能被分在几个不同的块里,三角形的数据(几何数据)可能被需要多次读取,但总的来说还是能大大减少对系统内存的访问,节约了带宽的同时也减少了电力消耗。 TBDR Tile Base Defered Rending 分块延迟渲染模式。该模式相对于TBR而言,在光栅化之后,有一个HSR(Hidden Surface Removal))硬件单元,通过对一个块内的三角形进行测试,剔除掉被遮挡的三角形,合成一幅由所有可见部分组成的画面,交给后续的流水线去渲染。这样不可见部分就不需要Pixel Shader去做相应的计算,也不需要去拾取相应的纹理,节省了计算量的同时也节省了带宽,对移动设备来说有很大的帮助。 Unified Shader 统一式渲染架构 即顶点着色器和片元着色器是共用同一个ALU Discrete Shader 分离式渲染架构 即顶点着色器和片元着色器是分开的,不共用同一个ALU GFLOPS FLOPS是Floating-point Operations Per Second 即每秒所执行的浮点运算次数的英文缩写。它是一个衡量计算机计算能力的量,这个量经常使用在那些需要大量浮点运算的科学运算中。有时也会被记为flop/s。GFLOPS就是 Giga Floating-point Operations Per Second。即每秒10亿次的浮点运算数,常作为GPU性能参数,但不一定代表GPU的实际表现,因为还要考虑具体如何拆分多边形和像素、以及纹理填充,理论上该数值越高越好。1GFlops = 1,000MFlops。 像素填充率 像素填充率是指图形处理单元在每秒内所渲染的像素数量,单位是MPixel/S(每秒百万像素),或者GPixel/S(每秒十亿像素),是用来度量当前显卡的像素处理性能的最常用指标。显卡的渲染管线是显示核心的重要组成部分,是显示核心中负责给图形配上颜色的一组专门通道。渲染管线越多,每组管线工作的频率(一般就是显卡的核心频率)越高,那么所绘出的显卡的填充率就越高,显卡的性能就越高,因此可以从显卡的象素填充率上大致判断出显卡的性能。像素填充率的最大值为3D时钟乘以渲染途径的数量。如NVIDIA的GeForce 2 GTS芯片,核心频率为200 MHz,4条渲染管道,每条渲染管道包含2个纹理单元。那么它的填充率就为4x2像素x2亿/秒=16亿像素/秒。 纹理填充率 纹理填充率是指一秒钟内纹理渲染的数目,计算公式为:3D芯片时钟 * 像素渲染管线数目 * 单个纹理使用的texel数目。例如:ATi Rage 128GL的主频为125MHz,有两条像素渲染管线。每条管线可以为一个双线性过滤像素上色,而双线性过滤需要4个texles。因此Rage 128GL纹理填充率为:125(时钟)* 2(像素渲染管线条数)* 4(texels)= 1000 Mtexels/s或1G texels/s。 显存带宽 显存带宽是指显示芯片与显存之间的数据传输速率,它以字节/秒为单位。显存带宽是决定显卡性能和速度最重要的因素之一。显存带宽=显存频率×显存位宽/8

Unity3D工程中的特殊文件夹及其在不同平台下的目录

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 目录名 作用 仅能放置于工程根目录吗 会打包进最终发布包吗 仅在编辑阶段使用吗 读取方式 打包时会原样保留原始文件格式吗 Editor 放置一些第三方或者自定义的编辑辅助工具的代码 N N Y - Editor Default Resources 编辑器用到的一些资源,比如图片、文本文件、等等。放在这里 Y N Y 调用EditorGUIUtility.Load读取 - Gizmos 用来在编辑阶段绘制一些辅助图标辅助线条 Y N Y 在MonoBehavior类的OnDrawGizmos方法中使用 - Plugins Andoird 或者 iOS平台下,要给工程接一些SDK时可以把SDK依赖的库文件如 .so .jar .a文件放置从此处 N Y N - N Resources Resources文件夹下的资源不管你用还是不用都会被打包进.apk或者.ipa N Y N Resource.Load函数: 编辑时和运行时都可以通过Resource.Load来直接读取。Resources.LoadAssetAtPath它可以读取Assets目录下的任意文件夹下的资源,它可以在编辑时或者编辑器运行时用,它但是它不能在真机上用,它的路径是 ”Assets/xx/xx.xxx” 必须是这种路径,并且要带文件的后缀名。 N StreamingAssets 并且它是一个只读的文件夹,就是程序运行时只能读 不能写。它在各个平台下的路径是不同的 N Y N Application.streamingAssetsPath 是访问这些目录下的资源路径的方法。它会根据当前的平台选择对应的路径。 Y Application类中定义的若干路径在不同平台下的具体值如下表: 变量Application.dataPath Windows: – Android: /data/app/xxx.xxx.xxx.apk iOS: Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data 变量Application.streamingAssetsPath

Unity3D的全局光照及Lighting Window面板参数简介

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 1 什么是全局光照(Global Illumination) 在阐述什么是全局光照之前,我们先简与之对应的局部光照。粗略地说,所谓局部光照,就是我们在渲染一个场景时,仅仅考虑光源和物体之间的交互,而不考虑物体与物体之间的光线交互——即每一个物体表面的颜色,仅仅由光源发出的光线贡献,而不考虑由其他物体所反射过来的光线的贡献。 全局光照则是在局部光照的基础上,增加考虑物体与物体之间光线交互。所以说如果局部光照系统就是由光源+待渲染物体+视点组成的话,那么全局光照系统就是由光源+各待渲染物体之间的反射光+待渲染物体+视点组成。 从是否是即时性来分,GI可分为实时(又可称为在线)光照和 非实时(又可称为离线) 光照。如果是离线光照的话,待渲染物体之间的反射光就是通过辐射度算法或者是光线追踪算法逐点计算出来的。这些算法是相当耗时的,无法应用在实时GI上(当然随着硬件的发展,不排除原本只适用于离线光照的算法在未来能应用在实时上)。 2 光照的各种方式 如上所述,GI是在局部光照的基础上,增加了对待渲染物体之间的光线交互的计算。从而使得渲染效果更逼真。对Unity3D而言。照明模式(lighting mode)分为实时照明和烘焙照明两大类,其中烘焙照明又可以分为预计算光照和烘焙光照贴图这两种。首先看实时照明的方式。 2.1 实时照明 在不做任何修改设置的情况下,Unity的光源(包括directional light,、spot light、point light)都是实时的,代表这些光源会把光线照射到场景并以每一帧的频率更新,由于光源是可以在场景内移动的对象,场景灯光的更新是实时的,你可以在游戏窗口和场景窗口看到改变。如下图 注意上图:因为没有反射光源的关系阴影是全黑的,只有投射光锥体范围内的对象表面才有光源影响。实时照明是场景里照亮物体最基本的方法,用来照亮角色和会动的对象,但默认设置里Unity实时照明里的光线不会反射,(也就是说,从A物体反射出来的光线,就算是在物理学上应该会入射到B物体。但在渲染中,计算B物体的最终颜色时,并不考虑这个从A物体反射过来的光线的贡献)。因此,我们才导入了全局光照系统,启用了预先计算的技术,都是为了表现一个更逼真的场景。 2.2 烘焙照明 2.2.1 烘焙全局光照贴图(Baked GI Lighting) 当烘焙一张光照贴图(Lightmap)时,场景内的静态对象会根据当前场景内的光照,算出一张渲染结果贴图,并覆盖在场景对象之上建立照明效果,如下图: 这些”光照贴图”可以包含场景内投射到物体表面的直接光源,以及在不同物体间反射的”间接光源”,这样的光照贴图可以通过使用着色器(Shader)描述物体的表面信息(Albedo)和凹凸(Normals)信息。 使用这种烘焙方式所产生出来的光照贴图,是无法在运行期发生变化的,因此被定义为静态(Static),虽然仍可在这层贴图上继续迭加光源计算,但两者已无法交互运算,通常我们采用这光照法来让低阶的手机能顺利执行,解决光在游戏中运行的性能问题。 2.2.2预计算全局光照(Precomputed Realtime GI Lighting) 虽然这种静态光照贴图无法在游戏执行时改变场景光照效果,但预先计算的实时全局光照系统,则能实时地去计算算复杂的场景光源的变化,通过这种方法,就能建立一个丰富的全局光照反射场景,并实时反映光源的改变。好比做个日晷,阴影的位置和颜色会随着光源移动改变,这在原本的烘焙光照系统是无法达成的。 为了能够实时地实现这些效果,需要在实时运算之前先将场景中的相关光照数据做一次”预计算”,所谓的预计算负责计算游戏过程中光的复杂行为,它可以在时间空档时进行计算,因此称作一个”脱机”运算,或者可称为“离线”运算。 3 Unity3D 5中的全局烘焙照明 在上节我们提到Unity3D 5的GI系统有两种烘焙模式,因此,Unity3D 5在Lighting Windows窗口中提供了这两种的模式的操作。 Unity3D 5的Lighting Window可以在通过菜单【Windows|Lighting】打开。 在Unity3D 5的灯光组件中,有一个Baking属性,这个Baking属性有三种选项,分别是Realtime、Baked、Mixed这三种属性。而这三种属性,则又分别对应于Lighting Window中的Scene Tab界面中的【Precomputed Realtime GI】和【Baked GI】这两个选项的组合,如下图 3.1只勾选【Precomputed Realtime GI】选项 关闭当在scene tab面板中,关闭了【Baked GI】选项。或者将场景中的全部光源类型设置为【Realtime】的时候这意味着没有任何的光会被预先烘焙出光照贴图。引擎在“烘焙”时,仅仅是存储场景内静态物体间的关系,当烘焙完成后你可以自由的调整光源或物体材质,并实时地看到效果。 此时在Scene中观察Baked结果可以看到没有任何静态颜色被烘焙出来。 如果在scene tab中,仅启用了【Precomputed Realtime GI】选项时,则场景中的光源应该选择Realtime类型。烘焙选项【Realtime Resolutio】对应前文所说的间接光照图,值越高间接光的效果就越明显(其实应该是越准确,当分辨率太低时间接光会因像素过滤而变弱) 。如下图,注意红色盒子投递在白色盒子上的影子。如下图当Realtime Resolution的值为10时 如下图当Realtime Resolution的值为1时 3.2 只勾选【Baked GI】选项 当在scene tab中,取消【Precomputed Realtime GI】选项,而启用【Baked GI】的话。这时候光源则依赖于他的Baking属性去分别参与静态光照贴图的烘焙:属性为Realtime的灯光,不参与静态光照烘焙,但同时作用于动态与静态物体上;属性为Mixed的光源,参与静态光照贴图的烘焙,而在运行时,则仅作用于非静态物体;属性为Baked光源,仅作用于静态光照贴图的烘焙,在运行时不参与实时光照计算。如下图可再次观察SceneView可以看到烘焙出来的颜色。

着色器语言的语义SV_POSITION和POSITION之辨析

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 简单地说POSITION语意用于顶点着色器,用来指定这些个位置坐标值,是在变换前的顶点的object space坐标。SV_POSITION语意则用于像素着色器,用来标识经过顶点着色器变换之后的顶点坐标。 SV是Systems Value的简写。在SV_Position的情况下,如果它是绑定在一个从VS输出的数据结构上的话,意味着这个输出的数据结构包含了最终的转换过的,将用于光栅器的顶点坐标。或者,如果你将这个标志绑定到一个输入给PS的数据数据的话,它会包含一个基于屏幕空间的像素的坐标。所有的这些SV语义都在DirectX SDK文档中有描述。 vertex shader将会输出顶点的坐标到裁剪空间中,并且这些坐标是使用齐次坐标系的。一般地,这些基于裁剪空间的齐次坐标,是通过对输入的对象空间坐标位置乘以一个WVP矩阵而得到的。然后在光栅器中,这些齐次坐标将会进行透视除法,即对这些坐标的每个分量除以w,做完透视除法后,这些坐标值将会限定在一个左下角是-1,右上角是1的视口范围中。然后做完“把Y坐标翻转,把取值范围从[-1,1]限制到[0,1],接着xy方向分别乘以视口的宽高”的视口变换之后,你便获得了“以SV_Position为标识的,传递给PS的,取值范围是[0,视口高宽],视口左上角为坐标原点的”像素位置坐标。 从D3D10开始出现的SV_Position语意,提供了类似于在Direct3D9对应的Shader Model3.0版本中的VPOS语意。在SM3.0中增加的VPOS语意,是特意用来表示某个像素点的坐标为屏幕空间坐标的。在D3D10及更高的版本中,SV_Position语意同样指定了某个像素点的坐标为屏幕空间坐标。但与VPOS不同的是,指定了SV_Position语意的屏幕空间坐标,光栅器已经自动地对这个值做了0.5像素的偏移,也就是说这个坐标对应的是该像素的中心点而不是左上角。