當前位置: 妍妍網 > 碼農

OpenGL 3D 渲染技術:glTF 基礎知識

2024-06-19碼農

大家好,我是程式設計師 kenney,今天給大家介紹 glTF 的基礎知識

glTF 是什麽?

它是 GL Transmission Format 的縮寫,是 khronos推 出的一種描述3D模型的格式,目標是使其成為一種通用的3D模型格式。它的官方github是 https://www.khronos.org/gltf/

我們知道3D模型有各種各樣的格式,如obj、FBX、dea等, 格式的多種多樣帶來了一個問題的就是各種軟體、渲染引擎、遊戲引擎之間的3D模型的不通用

例如在3D設計軟體中設計好一個3D模型之後,想把它放到一個渲染引擎中渲染,如果沒有一個通用的格式,渲染引擎可能也有一套自己的格式,這樣就要做格式轉換,而有些格式是不開源的,需要官方提供轉換工具,非常麻煩。

而如果有一個通用的格式大家都支持,這就好辦了,就像圖片中的jpeg一樣,通常的圖片編輯軟體都能匯出jpeg,通常的圖片檢視軟體也都能開啟,這就非常方便,而 glTF就是要成為3D模型界的 jpeg

glTF 是一用 json 格式編寫的 ,目前現在推出了2.0版本,本篇文章也是講解2.0版本,glTF格式中可以描述的資訊相當豐富,本篇文章先給大家介紹一些基礎的欄位:

  • 場景和節點描述:scenes、nodes

  • 網格描述:meshes

  • 數據描述:buffers、bufferViews、accessors

  • 材質描述:materials

  • 紋理、圖片和采樣器描述:textures、images、samplers

  • 攝影機描述:cameras

  • 總覽

    我們先來從一張圖總體上看一下glTF檔的結構,每一種型別的欄位,基本是都是用陣列來組織,在每個欄位中,又可以透過索引去參照其它欄位。

    它類似一個樹狀,但又不是嚴格的樹。

    最頂層的是場景,場景中包含了一些節點,節點中又可以套子節點,節點中可以有mesh、攝影機,如果是mesh,還可以為它指定材質及mesh網格數據,材質中可以指定純色及圖片紋理及其采樣配置,還可以描述蒙皮及動畫

    場景和節點

    場景和節點分別用scenes、nodes欄位描述,場景就是代表要渲染的一些東西的集合,場景裏麵包含一些節點,每個節點可以認為是一個物體(也可以是攝影機),節點也可以是空的,節點中可以繼續掛子結點。

    來看上面這個例子,scene欄位指定了使用第0個場景,一般來說,同一時刻只會渲染一個場景。

    scenes欄位是一個場景陣列,描述所有場景,這個例子中場景只有一個,它裏面的nodes欄位描述這個場景中有哪些節點,這裏是用索引為0、1、2的節點,它就對應了下面nodes陣列中第0、1、2個節。nodes欄位描述了所有節點,節點裏可以用children描述子節點,子節點的描述方式也是索引號。這樣,透過上圖左中的這段json,我們就描述了如上圖右中的那樣一個場景結構。

    可以為每個結點指定它的變換參數,這個變換參數是它相對於父節點的變換,可以用變換矩陣描述,也可以分別指定平移、旋轉和縮放。還可以指定它的mesh及攝影機,mesh就描述了這個節點是什麽物體,而camera會影響這個節點被觀察的樣子

    網格描述

    有了節點之後,我們要描述節點的東西是什麽,一個東西首先要有形狀,比如一個立方體,或者一個圓柱,這就需要meshs來描述:

    meshs同樣也是一個陣列,每個mesh中由primitives描述圖元,其中的mode是圖元的種類,也就是點、線或者三角形,indices表示accessors中的索引,後面會講到。

    attributes描述的是attribute的結構,裏面可以有頂點座標、紋理座標、法向量等,同樣也是以索引的方式參照accessors。最後的material表示這個mesh的材質,也是用索引來參照

    數據描述

    glTF中用buffers、bufferViews、accessors來描述數據:

    buffers是數據塊陣列,每個buffer由長度和路徑描述,bufferViews同樣也是陣列,其中每個bufferView表示一個buffer的檢視。這個怎麽理解呢?buffer是一堆純數據,它本身是不描述這堆數據用來做什麽的,而bufferView就可以理解成如何去看待這堆數據。

    其中buffer表示它對應的buffers中的索引。

    target描述了它是用來幹什麽的,比如上圖中的34963就對應了GL_ELEMENT_ARRAY_BUFFER,這個值是和OpenGL柯瑞定義的值是一致的,這樣使用起來就相當友好,glBindBuffer()可以直接傳這裏解析出來的target值而不用做對映轉換。

    byteOffset描述的是這塊buffer的偏移字節,byteLength是字節長度,bytteStride描述的是一個數據的開始距離下一個數據開始的跨度,如果相同語意的數據不是連續存在放的,bytteStride就會比一份數據的長度大,因為它要跨過其它型別的數據。

    再往下是accessors,它同樣也是一個陣列,其中每個accessor描述了對應bufferView中的數據以什麽樣的方式進行存取,在上圖上,偏移了4個欄位,以VEC2的方式取數據,即二維向量,向量每個成份的型別componentType是5126,它對應的是GL_FLOAT,count表示取數據的個數

    材質描述

    materials中每個元素是一個material

    例如上圖中的例子透過金屬度-粗糙度模型來描述材質,其中有一些材質紋理圖,比如基礎紋理圖、法向圖、遮擋紋理圖等,每個紋理圖透過index來對應紋理圖陣列中的索引,紋理座標也是類似的

    紋理、圖片和采樣器描述

    紋理、圖片和采樣器分別透過textures、images、samplers描述,看下面的例子

    textures中每個元素透過source索引到images陣列中,從而找到對應的紋理數據,images陣列中的元素可以以圖片路徑的方式提供圖片,也可以用bufferView的方式,bufferView最終又對應到一個數據塊上。

    samplers則描述了采樣器的配置,大家一看裏面的欄位就會很熟悉,同樣的,它也是直接對應了OpenGL柯瑞定義的值,解析出來直接使用,非常方便

    攝影機描述

    攝影機用cameras描述

    熟悉OpenGL的同學一眼就能看出裏面定義了一個透視投影相機和正交投影相機,以及視角、近/遠平面等參數,這個比較簡單,沒有太多好說的

    完整例子

    我們來看一下完整的例子,glTF官方提供了很多sample models:

    https://github.com/KhronosGroup/glTF-Sample-Models

    我選取了一個比較簡單的立方體,大家看完文章可以嘗試閱讀一下它的glTF檔,看看是否能理解其中的描述

    {
    "accessors" : [
    {
    "bufferView" : 0,
    "byteOffset" : 0,
    "componentType" : 5123,
    "count" : 36,
    "max" : [
    35
    ],
    "min" : [
    0
    ],
    "type" : "SCALAR"
    },
    {
    "bufferView" : 1,
    "byteOffset" : 0,
    "componentType" : 5126,
    "count" : 36,
    "max" : [
    1.000000,
    1.000000,
    1.000001
    ],
    "min" : [
    -1.000000,
    -1.000000,
    -1.000000
    ],
    "type" : "VEC3"
    },
    {
    "bufferView" : 2,
    "byteOffset" : 0,
    "componentType" : 5126,
    "count" : 36,
    "max" : [
    1.000000,
    1.000000,
    1.000000
    ],
    "min" : [
    -1.000000,
    -1.000000,
    -1.000000
    ],
    "type" : "VEC3"
    },
    {
    "bufferView" : 3,
    "byteOffset" : 0,
    "componentType" : 5126,
    "count" : 36,
    "max" : [
    1.000000,
    -0.000000,
    -0.000000,
    1.000000
    ],
    "min" : [
    0.000000,
    -0.000000,
    -1.000000,
    -1.000000
    ],
    "type" : "VEC4"
    },
    {
    "bufferView" : 4,
    "byteOffset" : 0,
    "componentType" : 5126,
    "count" : 36,
    "max" : [
    1.000000,
    1.000000
    ],
    "min" : [
    -1.000000,
    -1.000000
    ],
    "type" : "VEC2"
    }
    ],
    "asset" : {
    "generator" : "VKTS glTF 2.0 exporter",
    "version" : "2.0"
    },
    "bufferViews" : [
    {
    "buffer" : 0,
    "byteLength" : 72,
    "byteOffset" : 0,
    "target" : 34963
    },
    {
    "buffer" : 0,
    "byteLength" : 432,
    "byteOffset" : 72,
    "target" : 34962
    },
    {
    "buffer" : 0,
    "byteLength" : 432,
    "byteOffset" : 504,
    "target" : 34962
    },
    {
    "buffer" : 0,
    "byteLength" : 576,
    "byteOffset" : 936,
    "target" : 34962
    },
    {
    "buffer" : 0,
    "byteLength" : 288,
    "byteOffset" : 1512,
    "target" : 34962
    }
    ],
    "buffers" : [
    {
    "byteLength" : 1800,
    "uri" : "Cube.bin"
    }
    ],
    "images" : [
    {
    "uri" : "Cube_BaseColor.png"
    },
    {
    "uri" : "Cube_MetallicRoughness.png"
    }
    ],
    "materials" : [
    {
    "name" : "Cube",
    "pbrMetallicRoughness" : {
    "baseColorTexture" : {
    "index" : 0
    },
    "metallicRoughnessTexture" : {
    "index" : 1
    }
    }
    }
    ],
    "meshes" : [
    {
    "name" : "Cube",
    "primitives" : [
    {
    "attributes" : {
    "NORMAL" : 2,
    "POSITION" : 1,
    "TANGENT" : 3,
    "TEXCOORD_0" : 4
    },
    "indices" : 0,
    "material" : 0,
    "mode" : 4
    }
    ]
    }
    ],
    "nodes" : [
    {
    "mesh" : 0,
    "name" : "Cube"
    }
    ],
    "samplers" : [
    {}
    ],
    "scene" : 0,
    "scenes" : [
    {
    "nodes" : [
    0
    ]
    }
    ],
    "textures" : [
    {
    "sampler" : 0,
    "source" : 0
    },
    {
    "sampler" : 0,
    "source" : 1
    }
    ]
    }

    glTF有很多方法能方便地檢視效果,可以線上看,比如 gltf-viewer.donmccurdy.com ,上面那個glTF例子的渲染效果是這樣的

    謝謝閱讀!如有疑問,歡迎在評論區交流~

    歡迎關註我的 github:www.github.com/kenneycode

    原文連結: https://juejin.cn/post/6897480101177491463

    -- END --

    進技術交流群, 掃碼添加我的微信:Byte-Flow

    獲取相關資料和源碼

    學習音視訊、OpenGL ES、Vulkan 、Metal、影像濾鏡、視訊特效及相關渲染技術的付費社群,面試指導,1v1 簡歷服務,職業規劃。

    我的付費社群

    推薦: