我目前正在研究glTF作为WebGL项目的传输格式。我已经希望在WebGL客户端上呈现的几何图形可以作为预处理的顶点和索引缓冲区(和颜色缓冲区)使用,但是现在让我们忽略它们。

例如:

[       // vertex buffer
  0,0,0,
  0,1,0,
  1,0,0,
  1,1,0,
]

并绘制简单的LINES

[       // index buffer
  0,2,
  2,4,
  4,0,
  0,1,
  1,4,
]


我想知道如何创建包含这些缓冲区的glTF文件吗?

我想避免使用COLLADA和COLLADA2GLTF,因为这只会增加一个额外的步骤,并且可能只会膨胀生成的glTF文件。

#1 楼

在为教程创建一组glTF模型时,我还打算创建最小的glTF文件。


更新:以下内容指的是glTF 1.0 / 1.1。请参见下面的示例,将其更新为glTF 2.0。


正如5chdn在答复中已经提到的,可能是一个问题。根据规范的附录A:默认材质,不包含材质的资产应使用默认材质渲染,该材质仅以均匀的50%灰色显示对象。

有些观众可能不支持这一点,即使他们支持,在规范方面也有一些细微之处:在glTF 1.0中,仍然有必要定义“空”材料,因为mesh.primitive.material属性尚未可选。但这应该在glTF 1.1中修复。

因此,以下内容实际上应该是最小的glTF资产(1.1版):

{
  "scenes" : {
    "scene0" : {
      "nodes" : [ "node0" ]
    }
  },
  "nodes" : {
    "node0" : {
      "meshes" : [ "mesh0" ]
    }
  },

  "meshes" : {
    "mesh0" : {
      "primitives" : [ {
        "attributes" : {
          "POSITION" : "positionsAccessor"
        }
      } ]
    }
  },

  "buffers" : {
    "buffer0" : {
      "uri" : "data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA",
      "byteLength" : 36
    }
  },
  "bufferViews" : {
    "positionsBufferView" : {
      "buffer" : "buffer0",
      "byteOffset" : 0,
      "byteLength" : 36,
      "target" : 34962
    }
  },
  "accessors" : {
    "positionsAccessor" : {
      "bufferView" : "positionsBufferView",
      "byteOffset" : 0,
      "componentType" : 5126,
      "count" : 3,
      "type" : "VEC3",
      "max" : [ 1.0, 1.0, 0.0 ],
      "min" : [ 0.0, 0.0, 0.0 ]
    }
  },

  "asset" : {
    "version" : "1.1"
  }
}


它还显示了一个三角形:



没有嵌入式缓冲区的版本可以在https://github.com/javagl/gltfTutorialModels上找到,以及带有索引的三角形可以在https:// github上找到。 com / javagl / gltfTutorialModels / tree / master / Triangle


glTF 2.0的更新:


glTF 2.0的概念和顶级元素与glTF 1.0基本相同。但是格式仍然有所变化。最重要的是(对于这个小例子),顶级字典现在是数组。以下是与上述相同的“三角”模型,并进行了相应的更新:

{
   "scenes":[
      {
         "nodes":[ 0 ]
      }
   ],
   "nodes":[
      {
         "mesh":0
      }
   ],
   "meshes":[
      {
         "primitives":[
            {
               "attributes":{
                  "POSITION":1
               },
               "indices":0
            }
         ]
      }
   ],
   "buffers":[
      {
         "uri":"data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=",
         "byteLength":44
      }
   ],
   "bufferViews":[
      {
         "buffer":0,
         "byteOffset":0,
         "byteLength":6,
         "target":34963
      },
      {
         "buffer":0,
         "byteOffset":8,
         "byteLength":36,
         "target":34962
      }
   ],
   "accessors":[
      {
         "bufferView":0,
         "byteOffset":0,
         "componentType":5123,
         "count":3,
         "type":"SCALAR",
         "max":[
            2
         ],
         "min":[
            0
         ]
      },
      {
         "bufferView":1,
         "byteOffset":0,
         "componentType":5126,
         "count":3,
         "type":"VEC3",
         "max":[
            1.0,
            1.0,
            0.0
         ],
         "min":[
            0.0,
            0.0,
            0.0
         ]
      }
   ],
   "asset":{
      "version":"2.0"
   }
}


可以在glTF示例模型存储库中找到此glTF示例模型。

#2 楼

您可以将数据放入数据uri中以base64格式内联存储数据。

"buffers": {
    "a-buffer-id": {
        "byteLength": 1024,
        "type": "arraybuffer",
        "uri"="data:application/octet-stream;base64,..."
    }
},


与将数据存储在二进制文件中相比,它仍然有点肿。

#3 楼

在花了一些时间了解gltf文件中二进制缓冲区的工作方式之后,我终于设法生成了一个真正最小的gltf文件。这是一个黄色三角形(演示)。



我试图从gltf中删除不需要的所有内容。这似乎是必需的(github):

{
    "accessors": {
        "accessor0": {
            "bufferView": "bufferView0",
            "byteOffset": 0,
            "componentType": 5123,
            "count": 3,
            "type": "SCALAR"
        },
        "accessor1": {
            "bufferView": "bufferView1",
            "byteOffset": 0,
            "byteStride": 12,
            "componentType": 5126,
            "count": 3,
            "max": [
                0.5,
                0.5,
                0.5
            ],
            "min": [
                0.0,
                0.0,
                0.0
            ],
            "type": "VEC3"
        }
    },
    "asset": {
        "generator": "5chdn",
        "profile": {
            "api": "WebGL",
            "version": "1.0.3"
        },
        "version": "1.0",
        "extras": {
            "description": "minimal gltf, single triangle",
            "base64encoder": "https://jsfiddle.net/opkxy0xb/",
            "stackexchange": "https://computergraphics.stackexchange.com/q/1934/361"
        }
    },
    "bufferViews": {
        "bufferView0": {
            "buffer": "Min",
            "byteLength": 6,
            "byteOffset": 0,
            "target": 34963
        },
        "bufferView1": {
            "buffer": "Min",
            "byteLength": 36,
            "byteOffset": 6,
            "target": 34962
        }
    },
    "buffers": {
        "Min": {
            "bytelength": 42,
            "type": "arraybuffer",
            "uri": "data:application/octet-stream;base64,AAABAAIArK34PnZxmz29UhY9T6+UPXuD7z64QAI9UWuaPW/wBT3ysPA+"
        }
    },
    "materials": {
        "effect0": {
            "values": {
                "emission": [
                    0.8,
                    0.8,
                    0.0,
                    1.0
                ]
            },
            "technique": "technique0"
        }
    },
    "meshes": {
        "mesh0": {
            "name": "Triangle",
            "primitives": [
                {
                    "attributes": {
                        "POSITION": "accessor1"
                    },
                    "indices": "accessor0",
                    "material": "effect0",
                    "mode": 4
                }
            ]
        }
    },
    "nodes": {
        "node0": {
            "matrix": [
                1,
                0,
                0,
                0,
                0,
                1,
                0,
                0,
                0,
                0,
                1,
                0,
                0,
                0,
                0,
                1
            ],
            "meshes": [
                "mesh0"
            ],
            "name": "TriangleMesh"
        }
    },
    "programs": {
        "program0": {
            "attributes": [
                "a_position"
            ],
            "fragmentShader": "fragmentShader0",
            "vertexShader": "vertexShader0"
        }
    },
    "scenes": {
        "scene0": {
            "nodes": [
                "node0"
            ]
        }
    },
    "shaders": {
        "vertexShader0": {
            "type": 35633,
            "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdW5pZm9ybSBtYXQ0IHVfbW9kZWxWaWV3TWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfcHJvamVjdGlvbk1hdHJpeDsNCmF0dHJpYnV0ZSB2ZWMzIGFfcG9zaXRpb247DQp2b2lkIG1haW4odm9pZCkNCnsNCmdsX1Bvc2l0aW9uID0gdV9wcm9qZWN0aW9uTWF0cml4ICogdV9tb2RlbFZpZXdNYXRyaXggKiB2ZWM0KGFfcG9zaXRpb24sMS4wKTsNCn0="
        },
        "fragmentShader0": {
            "type": 35632,
            "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdW5pZm9ybSB2ZWM0IHVfZW1pc3Npb247DQp2b2lkIG1haW4odm9pZCkNCnsNCmdsX0ZyYWdDb2xvciA9IHVfZW1pc3Npb247DQp9"
        }
    },
    "techniques": {
        "technique0": {
            "attributes": {
                "a_position": "position"
            },
            "parameters": {
                "modelViewMatrix": {
                    "semantic": "MODELVIEW",
                    "type": 35676
                },
                "projectionMatrix": {
                    "semantic": "PROJECTION",
                    "type": 35676
                },
                "emission": {
                    "type": 35666
                },
                "position": {
                    "semantic": "POSITION",
                    "type": 35665
                }
            },
            "program": "program0",
            "states": {
                "enable": [
                    2884,
                    2929
                ]
            },
            "uniforms": {
                "u_modelViewMatrix": "modelViewMatrix",
                "u_projectionMatrix": "projectionMatrix",
                "u_emission": "emission"
            }
        }
    }
}


一个好的起点是gltf规范的附录A,它定义了默认的材质和着色器。我要做的就是添加场景描述和缓冲区。