实施vertex compression所遇到的各种问题和解决办法
关于顶点压缩,好处是可以减少带宽,一定程度提高加载速度,可以提高约5-10%的fps,特别是mobile上,简单描述就是:
压缩之前(32字节)
position float3 12
normal float3 12
texcoord0 float2 8
压缩之后(16字节)
position short4 8
normal ubyte4 4
texcoord0 short2 4
压缩的方法,其实就是在bounding box内分65536份,用"-32767.5"到"32767.5"描述。
参考文章:“Vertex Decompression using Vertex Shaders Part 2” by Dean Calve @ShaderX Programming
示例代码如下:
// 计算position的范围
oiram::vec3 posCenter( (mMesh.boundingBox.pmax.x + mMesh.boundingBox.pmin.x) * 0.5f,
(mMesh.boundingBox.pmax.y + mMesh.boundingBox.pmin.y) * 0.5f,
(mMesh.boundingBox.pmax.z + mMesh.boundingBox.pmin.z) * 0.5f), posExtent( (mMesh.boundingBox.pmax.x - mMesh.boundingBox.pmin.x) * 0.5f,
(mMesh.boundingBox.pmax.y - mMesh.boundingBox.pmin.y) * 0.5f,
(mMesh.boundingBox.pmax.z - mMesh.boundingBox.pmin.z) * 0.5f);
if (vertexDeclaration & oiram::Ves_Position)
{
oiram::vec4 norm((vertex.vec3Position.x - posCenter.x) / posExtent.x,
(vertex.vec3Position.y - posCenter.y) / posExtent.y,
(vertex.vec3Position.z - posCenter.z) / posExtent.z,
1.0f);
vertex.short4Position = oiram::short4(norm);
}
inline short packF32ToS16(float f)
{
return static_cast<short>(f * 32767.5f);;
} struct short4
{
short s[]; short4() {}
short4(const oiram::vec4& v)
{
s[] = packF32ToS16(v.x);
s[] = packF32ToS16(v.y);
s[] = packF32ToS16(v.z);
s[] = packF32ToS16(v.w);
}
};
这样,position的xyz就从float压缩到short中了。接下来,要在vs中进行解压,那么同样需要传入center和extent:
float4 position = float4(iPosition.xyz / 32767.5 * positionExtent + positionCenter, );
当然,这里可以直接将positionExtent除以32767.5之后再传入,减少一次不必要的除法操作,这属于自行研发优化的范畴之内,不累述。
接下来,同理可以将uv也进行压缩,因为uv是2个值的缘故,所以center和extent可以合并在一起,只占用一个float4即可,同上理不累述。
float4 texcoord0 = float4(iTexCoord0.xyzw * uvExtentCenter.xyxy + uvExtentCenter.zwzw);
需要注意的是,因为必须依赖vs进行解压,而且center和extent的值必须正确。有意思的是,如果美术曾经将一个展分过uv的大模型,摘取其中某一块,然后merge到一个新的模型中,那么就容易出现混乱的uv值,比如u = 1.234567e+28, v = 1.234567e-44#DEN之类的。如果打开3dsmax里的UV map观察,整个face的3个vertex都在uv上的同一个"点"上。无奈的是,获取这些数据的函数都正确返回了,而且uv数值也是正常的float,无法通过isNAN神码的来判断是否有效。唯一能想到的办法就是,检查uv的绝对值,如果小于0.00001,或者大于10000,就将其重置为0。
还有一个在顶点压缩之前不容易察觉的情况,因为某种原因,部分faces的material为空,即没有附上材质。这一些顶点之前可能安全地藏在模型的体内,肉眼无法察觉。但现在经过压缩之后,如果vs没有照顾到它们,将其正确得解压的话,因为是以short形式记录的,于是你会发现场景中出现一些奇异的巨形的模型,附着奇怪的贴图。
既然选择了programmable pipeline代替Fixed Function,那么意味着,你的shader在解压数据之余,渲染效果必须保持与之前FF的一致。可以想象的是,这并不是一件简单的事情,比如一个模型中,一部分submesh是用diffuse map渲染,另一部分submesh只用到了diffuse color。那么好吧,你的shader可要准备好了才行。
结论:一篇paper,一个算法,一种优化,往往看上去很简单很美好。当你往具体项目中加入时,通常不会像demo中执行得那么顺利,尤其是遇上大量的数据,甚至是各种奇葩数据,从而出现各种诡异现象的时候,那时候估计你就会跟我一样,很难笑得出来了。
实施vertex compression所遇到的各种问题和解决办法的更多相关文章
- Error: xz compression not available解决办法
centos6升级php时误安装: rpm -Uvh https://mirror.webtatic.com/yum/el7/epel-release.rpm rpm -Uvh https://mir ...
- vertex compression所遇到的问题
对于数据压缩,其实就是把浮点的32位精度,改用16位定点数来表达. 例如0.0 = 0,1.0 = 32767,-1.0 = -32767 这是一种有损压缩,会丢失一些精度,一般情况下是可以接受的. ...
- 执行start-dfs.sh后,datenode没有启动
Hadoop2.2.0启动异常 – Incompatible clusterIDs 2014年08月29日 ⁄ 综合 ⁄ 共 2399字 ⁄ 字号 小 中 大 ⁄ 评论关闭 今天启动Hadoop2.2 ...
- oracle 10g数据库下的 XDB组件的重新安装
emmmm,这是一个不做死就不会的过程!!! 今天在导出数据库时,遇到了报错信息,其实开发说这个报错没关系了,但作死如楼主,一定要把这个错给解决了,然后就有了下面的作死过程. 错误关键字是:packa ...
- Hadoop、Spark 集群环境搭建问题汇总
Hadoop 问题1: Hadoop Slave节点 NodeManager 无法启动 解决方法: yarn-site.xml reducer取数据的方式是mapreduce_shuffle 问题2: ...
- DDD实施经验分享—价值导向、从上往下进行(圈内第一个吃螃蟹DDD实施方案)
阅读目录: 1.背景 2.从业务开始 3.从战略到战术 4.借助外力推动研发(QA.领导.自动化测试) 5.领域模型与SAAS平台的内核(价值最大化) 6.最后 1.背景 DDD本身的技术就不介绍了, ...
- PHP Warning: ob_start() : output handler 'ob_gzhandler conflicts with 'zlib output compression'
安装phpcms过程中,会遇到Warning: ob_start() : output handler 'ob_gzhandler conflicts with 'zlib output compr ...
- Scrum实施调查案例
什么是敏捷开发方法?什么是SCRUM? 有人在这个字面上下功夫,说敏捷就是反应要灵敏,动作要快捷:有人还在字面上进行延伸,说敏捷就是又好又快,或者就是多快好省:有人说敏捷就是光写代码不写文档:有人觉得 ...
- 3G/4G网卡使用
整体架构: pppd call option & ----------↓---------- option脚本(设置PPP连接) ----------↓---------- chat脚本(进行 ...
随机推荐
- zabbix监控超详细搭建过程
监控及zabbix 目录: 1 监控分类... 1 1.1 硬件监控... 1 1.2 系统监控... 2 1.3 网络监控... 3 1.4 ...
- TestNG中用Parameters或DataProvider为测试方法传入参数
转载于网络 一.设置参数 测试方法是可以带有参数的.每个测试方法都可以带有任意数量的参数,并且可以通过使用TestNG的@Parameters向方法传递正确的参数. 设置方式有两种方法:使用 te ...
- servers中添加server时,看不到运行环境的选择。
servers中添加server时,看不到运行环境的选择. 主要原因是tomcat目录中的配置文件格式不对.
- 计算机图形学——OpenGL开发库开发库
vc++6.0 有 OpenGL 的东西.有头文件 GL.H, GLAUX.H, GLU.H 但没有 GLUT 软件包/工具包 如果想使用glut.h的话必须自己添加. 首先下载 OpenGL开发库, ...
- Android Studio项目结构
我们创建了一个Android Project,打开就如下图所示: 我们选择Project视图,就会有以下的项目文档结构: 上面笔者标注的数字是接下来要讲解的内容. 我们先来看1: 我们创建Appl ...
- 12.我们不是在真空里谈软件工程, 软件要运行在硬件芯片上面, 下面看看一个计算机芯片的发展历史: http://perspectives.mvdirona.com/2014/09/august-21-2014-computer-history-museum-presentation/ http://mvdirona.com/jrh/TalksAndPapers/DileepBhandar
电脑芯片的诞生和发展是20世纪最伟大的发明之一,芯片技术决定了计算机升级换代的速度,决定了计算机小型化实现的程度,决定了计算机智能化的程度,决定了计算机普及化的应用深度. 1971年11月15日,英特 ...
- RMQ_ST算法
RMQ (Range Minimum/Maximum Query)算法 1. 概述 RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数 ...
- oracle 锁表查询及解决、表字段查询
在进行批量对DML操作时程序竟然中断了,不再往下执行.查询一下某张表被锁住了,因此不再往下执行了 如果怀疑表被锁了,或者事务未被正常关闭,在Oracle数据库中我们可以通过以下语句进行查询获取相关信息 ...
- ServiceStack.Redis之IRedisClient<第三篇>
事实上,IRedisClient里面的很多方法,其实就是Redis的命令名.只要对Redis的命令熟悉一点就能够非常快速地理解和掌握这些方法,趁着现在对Redis不是特别了解,我也对着命令来了解一下这 ...
- Asp.Net Web API 2第十三课——ASP.NET Web API中的JSON和XML序列化
前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文描述ASP.NET W ...