惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
A
About on SuperTechFans
Apple Machine Learning Research
Apple Machine Learning Research
The Register - Security
The Register - Security
Vercel News
Vercel News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
人人都是产品经理
人人都是产品经理
MyScale Blog
MyScale Blog
云风的 BLOG
云风的 BLOG
博客园_首页
U
Unit 42
T
Tailwind CSS Blog
G
GRAHAM CLULEY
F
Full Disclosure
V
Vulnerabilities – Threatpost
T
Tenable Blog
月光博客
月光博客
P
Privacy & Cybersecurity Law Blog
P
Privacy International News Feed
K
Kaspersky official blog
Scott Helme
Scott Helme
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
N
News and Events Feed by Topic
T
The Exploit Database - CXSecurity.com
N
News and Events Feed by Topic
有赞技术团队
有赞技术团队
Recent Commits to openclaw:main
Recent Commits to openclaw:main
L
LINUX DO - 最新话题
Recorded Future
Recorded Future
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Help Net Security
Help Net Security
The GitHub Blog
The GitHub Blog
Cisco Talos Blog
Cisco Talos Blog
SecWiki News
SecWiki News
P
Proofpoint News Feed
Security Latest
Security Latest
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
罗磊的独立博客
S
Security Affairs
M
MIT News - Artificial intelligence
L
LINUX DO - 热门话题
美团技术团队
Simon Willison's Weblog
Simon Willison's Weblog
T
Threat Research - Cisco Blogs
Stack Overflow Blog
Stack Overflow Blog
Forbes - Security
Forbes - Security
Hugging Face - Blog
Hugging Face - Blog
博客园 - Franky
V
Visual Studio Blog

博客园 - 千里马肝

模型数据作渲染优化时遇到的问题 vertex compression所遇到的问题 depth and distance Linear or non-linear shadow maps? 【转】編譯Ogre1.9 IOS Dependencies及Ogre Source步驟及相關注意事項… 画之国 Le tableau (2011) 关于H.264 x264 h264 AVC1 解决Visual Studio 2010/2012的RC4011 warnings 解决Visual Studio 2010/2012在调试时lock文件的方法 神片和神回复 3DS Max 2014 features revealed 【西川善司】PLAYSTATION4图形讲座(后篇) [ 【西川善司】PLAYSTATION4图形讲座(前篇) 趣文:程序员/开发人员的真实生活 【转】25 things you probably didn't know about the 3ds Max SDK [讣告]“D之食卓”等代表作制作人饭野贤治逝世 楚汉传奇 【翻译】揭晓「Agni's Philosophy」幕后的"技术编" 【PS3/XB360】DEAD OR ALIVE 5 制作采访
实施vertex compression所遇到的各种问题和解决办法
千里马肝 · 2014-01-07 · via 博客园 - 千里马肝

关于顶点压缩,好处是可以减少带宽,一定程度提高加载速度,可以提高约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[4];

        short4() {}
        short4(const oiram::vec4& v)
        {
            s[0] = packF32ToS16(v.x);
            s[1] = packF32ToS16(v.y);
            s[2] = packF32ToS16(v.z);
            s[3] = packF32ToS16(v.w);
        }
    };

这样,position的xyz就从float压缩到short中了。接下来,要在vs中进行解压,那么同样需要传入center和extent:

float4 position = float4(iPosition.xyz / 32767.5 * positionExtent + positionCenter, 1);

当然,这里可以直接将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中执行得那么顺利,尤其是遇上大量的数据,甚至是各种奇葩数据,从而出现各种诡异现象的时候,那时候估计你就会跟我一样,很难笑得出来了。