gltf模型詳解

一、文件結(jié)構(gòu)

  一個gltf模型一般包含一下幾個文件:
  .bin   二進制文件存放頂點咬最、法線翎嫡、面、uv等數(shù)據(jù)
  .gltf  描述模型的綜合信息
  img文件夾  存放模型貼圖

二永乌、gltf模型信息詳解

1惑申、數(shù)據(jù)結(jié)構(gòu):
  {
    scene:0,
    scenes:[{nodes:0}],
    nodes:[
      {
         name:"rootModel",
         children:[1]
      },
      {
         name:"floor1",
         children:[2]
      },
      {
         name:"room1",
         mesh:0
      }
    ],
    meshes:[
        {
          name:"mesh1",
          primitives:[
              {attributes:{POSITION:0, NORMAL :1,TEXCOORD_0:0},indices:0, material:0,mode:4}
          ]
        }
    ],
    accessors:[
        {name:"postions_0", componentType:5126, count:100, bufferView:0, byteOffset:0,type:"VEC3",max:[],min:[]},
        {name:"texcoods_0", componentType:5126, count:100, bufferView:0, byteOffset:0,type:"VEC2",max:[],min:[]},
        {name:"indices_0", componentType:5123, count:100, bufferView:0, byteOffset:0,type:"SCALAR",max:[],min:[]}
    ],
    bufferViews:[
        {name:"view0",buffer:0,byteLength: 144, byteOffset: 0, byteStride: 12, target: 34962},
        {name:"view1",buffer:0,byteLength: 100, byteOffset: 144, byteStride: 8, target: 34962},
        {name:"view2",buffer:0,byteLength: 100, byteOffset: 244, byteStride: 8, target: 34962}
    ],
    buffers:[{name:1,uri:"1.bin"}],
    materials:[
        {name:"m0", pbrMetallicRoughness:{baseColorTexture:{index:0}}}
    ],
    textures:[{name:"t0",source:0}],
    images:[{name:"img0",uri:"1.jpg"]
    animations:[]
  }
2、概述

模型加載順序為铆遭,先加載gltf文件硝桩,然后解析依次讀取scenes、nodes枚荣、meshes碗脊、accessors、bufferViews橄妆、buffers衙伶、materials、textures害碾、images矢劲。其中每個mesh包括一個bufferViews和一個materials。每一層的遞進都有數(shù)組下標(biāo)來確定慌随。

3芬沉、各字段詳解
scenes 場景
  scenes:[{nodes:0}],
  scene:0

一般模型只有一個也是默認(rèn)場景阁猜,如果是多個丸逸,則根據(jù)對應(yīng)的scene字段確定哪一個是默認(rèn)場景,參考數(shù)據(jù)結(jié)構(gòu)部分的數(shù)據(jù)剃袍,每一個scene都包含一個nodes字段黄刚,指定了scene的根結(jié)點。本例中nodes對應(yīng)的值為0民效,代表根節(jié)點為nodes字段下對應(yīng)的第一個元素憔维。

nodes 節(jié)點
  nodes:[
  {
     name:"rootModel",
     children:[1]
  },
  {
     name:"floor1",
     children:[2]
  },
  {
     name:"room1",
     mesh:0
  }
]

nodes用來組裝模型層級涛救,第一個節(jié)點是父節(jié)點,children字段指定它所包含的子節(jié)點业扒。
nodes節(jié)點分為倆種检吆,一種是有children字段的,最終會渲染成group凶赁,一種是有mesh字段的最終渲染為mesh咧栗,mesh字段的值為meshes數(shù)組的小標(biāo)。

meshes 網(wǎng)絡(luò)
  meshes:[
    {
      name:"mesh1",
      primitives:[
          {attributes:{POSITION:0, NORMAL :1,TEXCOORD_0:0},indices:0, material:0,mode:4}
      ]
    }
]

網(wǎng)虱肄,由多個面和材質(zhì)組成致板,通過primitives字段指定。

  • attributes 指定了頂點咏窿、頂點法線斟或、uv坐標(biāo)在accessors數(shù)組的對應(yīng)數(shù)據(jù)的下標(biāo)。
    POSITION - 頂點
    NORMAL - 頂點法線集嵌,頂點法線不是必須萝挤,導(dǎo)入引擎 時可生成
    TEXCOORD_0 - uv坐標(biāo)
  • indices 指定了面在accessors數(shù)組的對應(yīng)數(shù)據(jù)的下標(biāo)
  • material 指定了該mesh的材質(zhì)在materials數(shù)組中的下標(biāo)
accessors 訪問器
  accessors:[
        {name:"postions_0", componentType:5126, count:100, bufferView:0, byteOffset:0,type:"VEC3",max:[],min:[]}
  ]

訪問器是鏈接bufferView和mesh之間的橋梁,主要作用是對bufferView中數(shù)據(jù)進行進一步描述

  • componentType 數(shù)據(jù)類型浮點或者整形
  • count 數(shù)量總和(頂點總數(shù)或者面總數(shù)根欧,通過此字段可計算模型的總頂點數(shù)怜珍、總面數(shù),對于模型性能分析和優(yōu)化有很大作用
  • bufferView 對應(yīng)數(shù)據(jù)在bufferViews中的下標(biāo)
bufferViews 緩沖區(qū)視圖
   bufferViews:[ 
      {name:"view0",buffer:0,byteLength: 144, byteOffset: 0, byteStride: 12, target: 34962}
   ]
  • buffer 對應(yīng)的數(shù)據(jù)在buffers數(shù)組中的下標(biāo)
  • byteLength 該緩沖區(qū)對于的數(shù)據(jù)長度
  • byteOffset 在buffer中的起始位置
buffers 緩沖區(qū)
  buffers:[{name:1,uri:"1.bin"}]
  • uri 該緩沖區(qū)對于的bin文件凤粗,bin文件的作用參考第一部分的介紹
從mesh走到bin文件酥泛,模型的骨骼已經(jīng)確定了,頂點嫌拣、法線柔袁、面、都有了异逐,剩下的就是給模型添加材質(zhì)貼圖捶索,這一部分也是從mesh出發(fā),由mesh下的material字段指定對應(yīng)的材質(zhì)
materials 材質(zhì)
  materials:[
        {name:"m0", pbrMetallicRoughness:{baseColorTexture:{index:0}}}
    ]
  • baseColorTexture 對應(yīng)textures數(shù)組下標(biāo)
textures 紋理
  textures:[{name:"t0",source:0}],
  • source 對應(yīng)images數(shù)組下標(biāo)
images 貼圖
  images:[{name:"img0",uri:"1.jpg"]

總的流程如下圖


gltf加載流程圖

三灰瞻、內(nèi)存占用

模型的內(nèi)存占用主要包括四個部分腥例,分別是內(nèi)存、gpu酝润、圖片緩存燎竖、cpu,其中主要決定性能的是gpu和圖片緩存

  • gpu :

對于gpu占用主要有一個問題袍祖,如何計算一個模型的gpu占用底瓣,有沒有公式可以算出來谢揪?針對這個問題就需要搞明白那些因素決定gpu占用蕉陋。

模型內(nèi)存占用圖

通過上圖很容易看出捐凭,gpu主要有面數(shù)、頂點數(shù)凳鬓、和紋理數(shù)茁肠、圖片尺寸有關(guān),仔細(xì)觀察頂點和面其實存在正相關(guān)的缩举,紋理數(shù)和圖片尺寸其實都屬于材質(zhì)垦梆,進而可以得出gpu=f(geomotry)+f(材質(zhì))。
對于材質(zhì)我們很容易得出f(材質(zhì))=4*1.33*\sum_{0}^{n}T_{n} .w*T_{n} .h
分析f(geomotry)仅孩,實際是有點托猩、面、法線辽慕、uv等數(shù)據(jù)決定京腥,其中大致可分為三部分,原始數(shù)據(jù)占用溅蛉、頂點著色器運行占用公浪、片元著色器占有。第一部分物理內(nèi)存占用可精確算出船侧,但后倆者只能粗略估算欠气,因為三角面可能共用頂點,gpu的計算能力也有波動镜撩,著色器程序更不可能相同预柒,因此我們只能估算,但面可能存在共點的情況琐鲁,因此我們可用一個頂點的最大內(nèi)存占用*頂點數(shù)估計一個這部分的最大gpu占用卫旱,所以

f(geomotry)=faces*f(fshader)+points*(4*8+f(vshader))

為了方便計算,我們用面替換點围段,一個最多對應(yīng)3個點因此可得

f(geomotry)=faces*(f(fshader)+96+3*f(vshader)

仔細(xì)觀察數(shù)據(jù)表顾翼,大致可以得出繪制一個面的所占有的內(nèi)存在0.8kb-3.1kb之間,我們?nèi)∽畲笾挡⑾蛏先≌卫幔梢源笾掳疵總€面3.1k的內(nèi)存去估算

最終可得出:
f(gpu) <= 4*1.33*\sum_{0}^{n}T_{n} .w*T_{n} .h+faces*3.1
(T代表單個材質(zhì)适贸,faces代表模型總面數(shù))

  • 圖片緩存 :

圖片緩存有很多文章說明,基本公式是
f=\sum_{0}^{n}img_{n}+4*img_{n}.w*img_{n}.h
圖片緩存其實是紋理緩存涝桅,對于場景切換拜姿,需要注意注銷紋理,釋放圖片緩存冯遂。

四蕊肥、性能優(yōu)化

有了上面的內(nèi)存占用,性能優(yōu)化的點就比較清晰了

  • 模型面數(shù)優(yōu)化
    可以在制作模型時,通過原始數(shù)據(jù)減少模型面數(shù)壁却,也可以通過腳本動態(tài)減面批狱,例如threejs的SimplifyModifier。
  • 紋理優(yōu)化


    紋理渲染流程圖

如果不追求過高的效果展东,可以直接減小圖片尺寸赔硫,如果對與效果要求很高,可以采用壓縮紋理技術(shù)

不同格式gpu占用

壓縮紋理方法主要是以上幾種盐肃,優(yōu)點是可以減少gpu占用提高渲染效率和初次渲染速度爪膊,缺點是這幾種文件通常會大于png圖片,而且兼容性很差砸王,這個問題直到去年有了比較好的解決方案 - basis_universal(https://github.com/BinomialLLC/basis_universal)推盛,谷歌聯(lián)合各大廠商解決了兼容性問題,原理參考下圖谦铃,basis文件在gpu端可根據(jù)不同設(shè)備的情況快速轉(zhuǎn)換為它支持的壓縮格式
basis紋理

  • 減少drawcall
    減少cpu與gpu通信次數(shù)小槐,類似于雪碧圖技術(shù),可通過合并mesh合并材質(zhì)等方法達(dá)到
    (附上一個查看工具:spector)
  • 光照
    適當(dāng)減少光源數(shù)荷辕,盡量用貼圖代替光照效果凿跳,如不需要光照剔除法線亦可減小模型物理內(nèi)存,提供渲染效率
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末疮方,一起剝皮案震驚了整個濱河市控嗜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌骡显,老刑警劉巖疆栏,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異惫谤,居然都是意外死亡壁顶,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門溜歪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來若专,“玉大人,你說我怎么就攤上這事蝴猪〉魉ィ” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵自阱,是天一觀的道長嚎莉。 經(jīng)常有香客問我,道長沛豌,這世上最難降的妖魔是什么趋箩? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上叫确,老公的妹妹穿的比我還像新娘爬早。我一直安慰自己,他們只是感情好启妹,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著醉旦,像睡著了一般饶米。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上车胡,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天檬输,我揣著相機與錄音,去河邊找鬼匈棘。 笑死丧慈,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的主卫。 我是一名探鬼主播逃默,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼簇搅!你這毒婦竟也來了完域?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤瘩将,失蹤者是張志新(化名)和其女友劉穎吟税,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姿现,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡肠仪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了备典。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片异旧。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖提佣,靈堂內(nèi)的尸體忽然破棺而出泽艘,到底是詐尸還是另有隱情,我是刑警寧澤镐依,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布匹涮,位于F島的核電站,受9級特大地震影響槐壳,放射性物質(zhì)發(fā)生泄漏然低。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望雳攘。 院中可真熱鬧带兜,春花似錦、人聲如沸吨灭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喧兄。三九已至无畔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吠冤,已是汗流浹背浑彰。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拯辙,地道東北人郭变。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像涯保,于是被迫代替她去往敵國和親诉濒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容