|
| 1 | +Previous: [Cameras](gltfTutorial_018_Cameras.md) | [Table of Contents](README.md) | Next: [Skins](gltfTutorial_020_Skins.md) |
| 2 | + |
| 3 | +**NOTE: Parts of the skinning may undergo minor changes for glTF 1.1. See https://github.com/KhronosGroup/glTF/issues/723 and https://github.com/KhronosGroup/glTF/issues/624** |
| 4 | + |
| 5 | + |
| 6 | +# A simple skin |
| 7 | + |
| 8 | + |
| 9 | +glTF supports *vertex skinning*, which allows the geometry (vertices) of a mesh to be deformed based on the pose of a skeleton. This is essential in order to give animated geometry, for example of virtual characters, a realistic appearance. The core for the definition of vertex skinning in a glTF asset is the [`skin`](https://github.com/KhronosGroup/glTF/tree/master/specification#reference-skin), but vertex skinning in general implies several interdependencies between the elements of a glTF asset that have been presented so far. |
| 10 | + |
| 11 | +The following is a glTF asset that shows basic vertex skinning for a simple geometry. The elements of this asset will be summarized quickly in this section, referring to the previous sections where appropriate, and pointing out the new elements that have been added for the vertex skinning functionality. The details and background information for vertex skinning will be given in the next section. |
| 12 | + |
| 13 | +```javascript |
| 14 | +{ |
| 15 | + "scenes" : { |
| 16 | + "scene0" : { |
| 17 | + "nodes" : [ "node0" ] |
| 18 | + } |
| 19 | + }, |
| 20 | + "nodes" : { |
| 21 | + "node0" : { |
| 22 | + "meshes" : [ "mesh0" ], |
| 23 | + "skeletons": [ "jointNode0" ], |
| 24 | + "skin": "simpleSkin" |
| 25 | + }, |
| 26 | + "jointNode0" : { |
| 27 | + "jointName" : "joint0", |
| 28 | + "children" : [ "jointNode1" ], |
| 29 | + "translation" : [ 0.0, 1.0, 0.0 ] |
| 30 | + }, |
| 31 | + "jointNode1" : { |
| 32 | + "jointName" : "joint1", |
| 33 | + "rotation" : [ 0.0, 0.0, 0.0, 1.0 ] |
| 34 | + } |
| 35 | + }, |
| 36 | + |
| 37 | + "skins": { |
| 38 | + "simpleSkin": { |
| 39 | + "bindShapeMatrix": [ |
| 40 | + 1.0, 0.0, 0.0, 0.0, |
| 41 | + 0.0, 1.0, 0.0, 0.0, |
| 42 | + 0.0, 0.0, 1.0, 0.0, |
| 43 | + -0.5, 0.0, 0.0, 1.0 |
| 44 | + ], |
| 45 | + "jointNames": [ |
| 46 | + "joint0", |
| 47 | + "joint1" |
| 48 | + ], |
| 49 | + "inverseBindMatrices": "inverseBindMatricesAccessor" |
| 50 | + } |
| 51 | + }, |
| 52 | + |
| 53 | + "animations": { |
| 54 | + "animation0": { |
| 55 | + "samplers" : { |
| 56 | + "rotationSampler" : { |
| 57 | + "input" : "timeAccessor", |
| 58 | + "interpolation" : "LINEAR", |
| 59 | + "output" : "rotationAccessor" |
| 60 | + } |
| 61 | + }, |
| 62 | + "channels" : [ { |
| 63 | + "sampler" : "rotationSampler", |
| 64 | + "target" : { |
| 65 | + "id" : "jointNode1", |
| 66 | + "path" : "rotation" |
| 67 | + } |
| 68 | + } ] |
| 69 | + } |
| 70 | + }, |
| 71 | + |
| 72 | + "meshes" : { |
| 73 | + "mesh0" : { |
| 74 | + "primitives" : [ { |
| 75 | + "attributes" : { |
| 76 | + "POSITION" : "positionsAccessor", |
| 77 | + "JOINT" : "jointsAccessor", |
| 78 | + "WEIGHT" : "weightsAccessor" |
| 79 | + }, |
| 80 | + "indices" : "indicesAccessor", |
| 81 | + "material" : "simpleSkinMaterial" |
| 82 | + } ] |
| 83 | + } |
| 84 | + }, |
| 85 | + |
| 86 | + |
| 87 | + "materials": { |
| 88 | + "simpleSkinMaterial": { |
| 89 | + "technique": "simpleSkinTechnique" |
| 90 | + } |
| 91 | + }, |
| 92 | + |
| 93 | + "techniques": { |
| 94 | + "simpleSkinTechnique": { |
| 95 | + "attributes": { |
| 96 | + "a_position": "position", |
| 97 | + "a_joint": "joint", |
| 98 | + "a_weight": "weight" |
| 99 | + }, |
| 100 | + "uniforms": { |
| 101 | + "u_jointMat": "jointMat", |
| 102 | + "u_modelViewMatrix": "modelViewMatrix", |
| 103 | + "u_projectionMatrix": "projectionMatrix" |
| 104 | + }, |
| 105 | + "parameters": { |
| 106 | + "position": { |
| 107 | + "semantic": "POSITION", |
| 108 | + "type": 35665 |
| 109 | + }, |
| 110 | + "joint": { |
| 111 | + "semantic": "JOINT", |
| 112 | + "type": 35666 |
| 113 | + }, |
| 114 | + "weight": { |
| 115 | + "semantic": "WEIGHT", |
| 116 | + "type": 35666 |
| 117 | + }, |
| 118 | + "jointMat": { |
| 119 | + "count": 2, |
| 120 | + "semantic": "JOINTMATRIX", |
| 121 | + "type": 35676 |
| 122 | + }, |
| 123 | + "modelViewMatrix": { |
| 124 | + "semantic": "MODELVIEW", |
| 125 | + "type": 35676 |
| 126 | + }, |
| 127 | + "projectionMatrix": { |
| 128 | + "semantic": "PROJECTION", |
| 129 | + "type": 35676 |
| 130 | + } |
| 131 | + }, |
| 132 | + "program": "simpleSkinProgram", |
| 133 | + "states": { |
| 134 | + "enable": [ |
| 135 | + 2929 |
| 136 | + ] |
| 137 | + } |
| 138 | + } |
| 139 | + }, |
| 140 | + |
| 141 | + "programs": { |
| 142 | + "simpleSkinProgram": { |
| 143 | + "attributes": [ |
| 144 | + "a_position", |
| 145 | + "a_joint", |
| 146 | + "a_weight" |
| 147 | + ], |
| 148 | + "vertexShader": "simpleSkinVertexShader", |
| 149 | + "fragmentShader": "simpleSkinFragmentShader" |
| 150 | + } |
| 151 | + }, |
| 152 | + "shaders": { |
| 153 | + "simpleSkinVertexShader": { |
| 154 | + "type": 35633, |
| 155 | + "uri": "simpleSkin.vert" |
| 156 | + }, |
| 157 | + "simpleSkinFragmentShader": { |
| 158 | + "type": 35632, |
| 159 | + "uri": "simpleSkin.frag" |
| 160 | + } |
| 161 | + }, |
| 162 | + |
| 163 | + |
| 164 | + "buffers" : { |
| 165 | + "geometryBuffer" : { |
| 166 | + "uri" : "data:application/octet-stream;base64,AAABAAMAAAADAAIAAgADAAUAAgAFAAQABAAFAAcABAAHAAYABgAHAAkABgAJAAgAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAD8AAAAAAACAPwAAAD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAwD8AAAAAAACAPwAAwD8AAAAAAAAAAAAAAEAAAAAAAACAPwAAAEAAAAAA", |
| 167 | + "byteLength" : 168 |
| 168 | + }, |
| 169 | + "skinDataBuffer" : { |
| 170 | + "uri" : "data:application/octet-stream;base64,AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAABAPwAAgD4AAAAAAAAAAAAAQD8AAIA+AAAAAAAAAAAAAAA/AAAAPwAAAAAAAAAAAAAAPwAAAD8AAAAAAAAAAAAAgD4AAEA/AAAAAAAAAAAAAIA+AABAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAA=", |
| 171 | + "byteLength" : 320 |
| 172 | + }, |
| 173 | + "inverseBindMatricesBuffer" : { |
| 174 | + "uri" : "data:application/octet-stream;base64,AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAMAAAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAgD8=", |
| 175 | + "byteLength" : 128 |
| 176 | + }, |
| 177 | + "animationBuffer" : { |
| 178 | + "uri" : "data:application/octet-stream;base64,AAAAAAAAAD8AAIA/AADAPwAAAEAAACBAAABAQAAAYEAAAIBAAACQQAAAoEAAALBAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAkxjEPkSLbD8AAAAAAAAAAPT9ND/0/TQ/AAAAAAAAAAD0/TQ/9P00PwAAAAAAAAAAkxjEPkSLbD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAkxjEvkSLbD8AAAAAAAAAAPT9NL/0/TQ/AAAAAAAAAAD0/TS/9P00PwAAAAAAAAAAkxjEvkSLbD8AAAAAAAAAAAAAAAAAAIA/", |
| 179 | + "byteLength" : 240 |
| 180 | + } |
| 181 | + }, |
| 182 | + |
| 183 | + "bufferViews" : { |
| 184 | + "indicesBufferView" : { |
| 185 | + "buffer" : "geometryBuffer", |
| 186 | + "byteOffset" : 0, |
| 187 | + "byteLength" : 48, |
| 188 | + "target" : 34963 |
| 189 | + }, |
| 190 | + "positionsBufferView" : { |
| 191 | + "buffer" : "geometryBuffer", |
| 192 | + "byteOffset" : 48, |
| 193 | + "byteLength" : 120, |
| 194 | + "target" : 34962 |
| 195 | + }, |
| 196 | + "skinDataBufferView" : { |
| 197 | + "buffer" : "skinDataBuffer", |
| 198 | + "byteOffset" : 0, |
| 199 | + "byteLength" : 320, |
| 200 | + "target" : 34962 |
| 201 | + }, |
| 202 | + "inverseBindMatricesBufferView" : { |
| 203 | + "buffer" : "inverseBindMatricesBuffer", |
| 204 | + "byteOffset" : 0, |
| 205 | + "byteLength" : 128 |
| 206 | + }, |
| 207 | + "animationBufferView" : { |
| 208 | + "buffer" : "animationBuffer", |
| 209 | + "byteOffset" : 0, |
| 210 | + "byteLength" : 240 |
| 211 | + } |
| 212 | + }, |
| 213 | + "accessors" : { |
| 214 | + "indicesAccessor" : { |
| 215 | + "bufferView" : "indicesBufferView", |
| 216 | + "byteOffset" : 0, |
| 217 | + "componentType" : 5123, |
| 218 | + "count" : 24, |
| 219 | + "type" : "SCALAR", |
| 220 | + "max" : [ 9 ], |
| 221 | + "min" : [ 0 ] |
| 222 | + }, |
| 223 | + "positionsAccessor" : { |
| 224 | + "bufferView" : "positionsBufferView", |
| 225 | + "byteOffset" : 0, |
| 226 | + "componentType" : 5126, |
| 227 | + "count" : 10, |
| 228 | + "type" : "VEC3", |
| 229 | + "max" : [ 1.0, 2.0, 0.0 ], |
| 230 | + "min" : [ 0.0, 0.0, 0.0 ] |
| 231 | + }, |
| 232 | + "jointsAccessor" : { |
| 233 | + "bufferView" : "skinDataBufferView", |
| 234 | + "byteOffset" : 0, |
| 235 | + "componentType" : 5126, |
| 236 | + "count" : 10, |
| 237 | + "type" : "VEC4", |
| 238 | + "max" : [ 1.0, 1.0, 0.0, 0.0 ], |
| 239 | + "min" : [ 0.0, 0.0, 0.0, 0.0 ] |
| 240 | + }, |
| 241 | + "weightsAccessor" : { |
| 242 | + "bufferView" : "skinDataBufferView", |
| 243 | + "byteOffset" : 160, |
| 244 | + "componentType" : 5126, |
| 245 | + "count" : 10, |
| 246 | + "type" : "VEC4", |
| 247 | + "max" : [ 1.0, 1.0, 0.0, 0.0 ], |
| 248 | + "min" : [ 0.0, 0.0, 0.0, 0.0 ] |
| 249 | + }, |
| 250 | + "inverseBindMatricesAccessor" : { |
| 251 | + "bufferView" : "inverseBindMatricesBufferView", |
| 252 | + "byteOffset" : 0, |
| 253 | + "componentType" : 5126, |
| 254 | + "count" : 2, |
| 255 | + "type" : "MAT4", |
| 256 | + "max" : [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, 1.0], |
| 257 | + "min" : [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -2.0, 0.0, 1.0] |
| 258 | + }, |
| 259 | + "timeAccessor" : { |
| 260 | + "bufferView" : "animationBufferView", |
| 261 | + "byteOffset" : 0, |
| 262 | + "componentType" : 5126, |
| 263 | + "count" : 12, |
| 264 | + "type" : "SCALAR", |
| 265 | + "max" : [ 1.0 ], |
| 266 | + "min" : [ 0.0 ] |
| 267 | + }, |
| 268 | + "rotationAccessor" : { |
| 269 | + "bufferView" : "animationBufferView", |
| 270 | + "byteOffset" : 48, |
| 271 | + "componentType" : 5126, |
| 272 | + "count" : 12, |
| 273 | + "type" : "VEC4", |
| 274 | + "max" : [ 0.0, 0.0, 0.707, 1.0 ], |
| 275 | + "min" : [ 0.0, 0.0, -0.707, -0.707 ] |
| 276 | + } |
| 277 | + }, |
| 278 | + "asset" : { |
| 279 | + "version" : "1.1" |
| 280 | + } |
| 281 | +} |
| 282 | + |
| 283 | +``` |
| 284 | + |
| 285 | +The vertex shader for this example has special uniform variables that are required for vertex skinning, because the deformed positions of the vertices will actually be computed by the vertex shader. These uniforms will also be explained later. For now, here is the source code of the vertex shader, which is stored in `simpleSkin.vert`: |
| 286 | + |
| 287 | +```glsl |
| 288 | +#ifdef GL_ES |
| 289 | + precision highp float; |
| 290 | +#endif |
| 291 | +
|
| 292 | +attribute vec3 a_position; |
| 293 | +
|
| 294 | +attribute vec4 a_joint; |
| 295 | +attribute vec4 a_weight; |
| 296 | +
|
| 297 | +uniform mat4 u_jointMat[2]; |
| 298 | +
|
| 299 | +uniform mat4 u_modelViewMatrix; |
| 300 | +uniform mat4 u_projectionMatrix; |
| 301 | +
|
| 302 | +void main(void) |
| 303 | +{ |
| 304 | + mat4 skinMat = |
| 305 | + a_weight.x * u_jointMat[int(a_joint.x)] + |
| 306 | + a_weight.y * u_jointMat[int(a_joint.y)] + |
| 307 | + a_weight.z * u_jointMat[int(a_joint.z)] + |
| 308 | + a_weight.w * u_jointMat[int(a_joint.w)]; |
| 309 | + vec4 pos = u_modelViewMatrix * skinMat * vec4(a_position,1.0); |
| 310 | + gl_Position = u_projectionMatrix * pos; |
| 311 | +} |
| 312 | +``` |
| 313 | + |
| 314 | + |
| 315 | +The fragment shader for this example is trivial, and only assigns a constant color to all fragments. Its source code is stored in `simpleSkin.frag`: |
| 316 | + |
| 317 | +```glsl |
| 318 | +#ifdef GL_ES |
| 319 | + precision highp float; |
| 320 | +#endif |
| 321 | +
|
| 322 | +void main(void) |
| 323 | +{ |
| 324 | + gl_FragColor = vec4(0.8, 0.5, 0.1, 1.0); |
| 325 | +} |
| 326 | +} |
| 327 | +``` |
| 328 | + |
| 329 | + |
| 330 | +The result of rendering this asset is shown in the following screenshot: |
| 331 | + |
| 332 | +<p align="center"> |
| 333 | +<img src="images/simpleSkin.gif" /><br> |
| 334 | +<a name="simpleSkin-gif"></a>Image 19a: A scene with simple vertex skinning |
| 335 | +</p> |
| 336 | + |
| 337 | + |
| 338 | +## Elements of the simple skin example |
| 339 | + |
| 340 | +The elements of the given example are summarized here quickly: |
| 341 | + |
| 342 | +- The `scenes` and `nodes` elements have been explained in the [Scenes and Nodes](gltfTutorial_004_ScenesNodes.md) section. For the vertex skinning, new nodes have been added: The `"jointNode0"` and `"jointNode1`" define a new node hierarchy for the *skeleton*. These nodes can be considered as the joints between the "bones" that will eventually cause the deformation of the mesh |
| 343 | +- The new top-level dictionary `skins` contains a single skin in the given example. The properties of this skin object will be explained later. |
| 344 | +- The concepts of `animations` has been explained in the [Animations](gltfTutorial_007_Animations.md) section. In the given example, the animation refers to the *skeleton* nodes, so that the effect of the vertex skinning is actually visible during the animation. |
| 345 | +- The section about [Meshes](gltfTutorial_009_Meshes.md) already explained the contents of the `meshes` and `mesh.primitive` objects. In this example, new mesh primitive attributes have been added, which are required for vertex skinning, namely the `"JOINTS"` and `"WEIGHTS"` attributes |
| 346 | +- Details about the `materials`, `techniques` `programs` and `shaders` can be found in the sections about [Materials and Techniques](gltfTutorial_013_MaterialsTechniques.md) and [Programs and Shaders](gltfTutorial_012_ProgramsShaders.md), respectively. In the given example, there is a single program that refers to the shaders shown above, and a single technique that defines the new technique parameters that are required for vertex skinning. |
| 347 | +- There are several new `buffers`, `bufferViews` and `accessors`. Their basic properties have been described in the [Buffers, BufferViews, Accessors](gltfTutorial_005_BufferBufferViewsAccessors.md) section. In the given example, they contain the additional data that is required for vertex skinning. |
| 348 | + |
| 349 | +The details about how these elements are interconnected to achive the vertex skinning will be explained in the following section about [Skins](gltfTutorial_020_Skins.md). |
| 350 | + |
| 351 | + |
| 352 | +Previous: [Cameras](gltfTutorial_018_Cameras.md) | [Table of Contents](README.md) | Next: [Skins](gltfTutorial_020_Skins.md) |
0 commit comments