实施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[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中執行得那么順利,尤其是遇上大量的數據,甚至是各種奇葩數據,從而出現各種詭異現象的時候,那時候估計你就會跟我一樣,很難笑得出來了。
?
?
轉載于:https://www.cnblogs.com/oiramario/p/3508097.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的实施vertex compression所遇到的各种问题和解决办法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信小程序登录 php后台
- 下一篇: webstorm主题设置