-
Notifications
You must be signed in to change notification settings - Fork 210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial commit of first glTF tutorial #1
Conversation
Thanks so much @javagl! This is a major contribution to the community! I will review your glTF tutorials soon. Other folks that may want to review are:
Direct link to tutorials: https://github.com/javagl/glTF-Tutorials/tree/master/gltfTutorial#gltf-tutorial |
gltfTutorial/README.md
Outdated
|
||
This tutorial gives an introduction to [glTF](https://www.khronos.org/gltf), the GL transmission format. It summarizes the most important features and application cases of glTF, and describes the structure of the files that are related to glTF. It explains how glTF files may be read, processed and used to display 3D graphics efficiently. | ||
|
||
Some basic knowledge about [JSON](http://json.org/), the JavaScript Object Notation, and about [OpenGL](https://www.khronos.org/opengl/) is required. Where appropriate, the related concepts of OpenGL will be explained quickly, usually with examples in [WebGL](https://www.khronos.org/webgl/). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit confusing worded as is. Perhaps say something like "knowledge of a graphics API...examples will be in WebGL."
gltfTutorial/README.md
Outdated
|
||
Some basic knowledge about [JSON](http://json.org/), the JavaScript Object Notation, and about [OpenGL](https://www.khronos.org/opengl/) is required. Where appropriate, the related concepts of OpenGL will be explained quickly, usually with examples in [WebGL](https://www.khronos.org/webgl/). | ||
|
||
- [Introduction](gltfTutorial_001_Introduction.md) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can each .md file link to the previous, next, and contents?
|
||
## Introduction to glTF | ||
|
||
There is an increasing number of applications and services that are based on 3D content. Online shops are offering product configurators with a 3D preview. Museums are digitizing their artifacts with 3D scans, and allow exploring their collection in virtual galleries. City planners are using 3D city models for planning and information visualization. Educators are creating interactive, animated 3D models of the human body. In many cases, these applications are running directly in the web browser, which is possible because all modern browsers support efficient, OpenGL-based rendering with WebGL. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here as well, the "OpenGL-based rendering with WebGL" is confusing.
I suggest positioning statements like this as "graphics API in general (could be OpenGL, Vulkan, D3D, etc); WebGL examples for this tutorial" since this is the direction for glTF.
|
||
There is an increasing number of applications and services that are based on 3D content. Online shops are offering product configurators with a 3D preview. Museums are digitizing their artifacts with 3D scans, and allow exploring their collection in virtual galleries. City planners are using 3D city models for planning and information visualization. Educators are creating interactive, animated 3D models of the human body. In many cases, these applications are running directly in the web browser, which is possible because all modern browsers support efficient, OpenGL-based rendering with WebGL. | ||
|
||
 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to have captions for each figure, or label them as (a), (b), etc.
so the descriptions can be connected.
|
||
### 3D content creation | ||
|
||
The 3D content that is rendered in the client application comes from different sources. In some cases, the raw 3D data is obtained with a 3D scanner, and the resulting geometry data is stored as the [OBJ](https://en.wikipedia.org/wiki/Wavefront_.obj_file), [PLY](https://en.wikipedia.org/wiki/PLY_(file_format)) or [STL](https://en.wikipedia.org/wiki/STL_(file_format)) files. These file formats only support simple geometric objects and do not contain information about how the objects should be rendered. Additionally, they cannot describe more complex 3D scenes that involve multiple objects. Such sophisticated 3D scenes can be created with authoring tools. These tools allow editing the overall structure of the scene, the light setup, cameras, animations, and, of course, the 3D geometry of the objects that appear in the scene. Each authoring tool defines its own file format in which the 3D scenes are stored. For example, [Blender](https://www.blender.org/) stores the scenes in `.blend` files, [LightWave3D](https://www.lightwave3d.com/) uses the `.lws` file format, [3ds Max](http://www.autodesk.com/3dsmax) uses the `.max` file format, and [Maya](http://www.autodesk.com/maya) scenes are stored as `.ma` files. For the exchange of data between 3D authoring applications, different standard file formats have been developed. For example, Autodesk has defined the [FBX](http://www.autodesk.com/products/fbx/overview) format. The web3D consortium has set up [VRML and X3D](http://www.web3d.org/standards) as international standards for web-based 3D graphics. And the [COLLADA](https://www.khronos.org/collada/) specification defines an XML-based data exchange format for 3D authoring tools. The [List of 3D graphics file formats on Wikipedia](https://en.wikipedia.org/wiki/List_of_file_formats#3D_graphics) shows that there is an overwhelming number of more than 70 different file formats for 3D data, serving different purposes and application cases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This paragraph is really long. Consider breaking it up into two or three paragraphs.
If you have some spare time, I really love this book on writing: http://www.bartleby.com/141/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This paragraph does a nice job of setting the context for glTF in the sea of 3D formats. It would be awesome to complement it with a figure that shows how formats are grouped/relate.
gltfTutorial/README.md
Outdated
@@ -0,0 +1,18 @@ | |||
#glTF Tutorial |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps add an Acknowledgements section to the bottom of this .md file and add everyone who contributes content, provides feedback, edits, etc. This may help encourage contributions and tie together the glTF community.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps rename this to something like "Introduction to glTF using WebGL"
|
||
### 3D content rendering | ||
|
||
Although there are so many different file formats for 3D data, there is only one open, truly platform-independent and versatile way of *rendering* 3D content - and that is OpenGL. It is used for high-performance rendering applications on the desktop, on smartphones, and directly in the web browser, using WebGL. In order to render a 3D scene that was created with an authoring tool, the input data has to be parsed, and the 3D geometry data has to be converted into the format that is required by OpenGL. The 3D data has to be transferred to the graphics card memory, and then the rendering process can be described with shader programs and sequences of OpenGL API calls. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest repositioning this as described above.
Set the stage that there is a gap between content tools and rendering content with graphics APIs (again, could be OpenGL, WebGL, Vulkan, D3D, etc.). Each game/graphics engine has solved this with their own format and their own toolchain. That is silly; we can move the field forward faster if we collaborate around an open standard - glTF
|
||
 | ||
|
||
The existing file formats are not appropriate for this use case: Some of them are do not contain any scene information, but only geometry data. Others have been designed for exchanging data between authoring applications, and their main goal is to retain as much information about the 3D scene as possible. As a result, the files are usually large, complex and hard to parse. None of the existing file formats was designed for the use case of efficiently transferring 3D scenes over the web and rendering them as efficiently as possible with OpenGL. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"are do not" -> "do not"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"hard to parse" -> not just hard to parse; they are hard to fully process so that we can generate draw calls. For example, COLLADA has polygons that would need to be triangulated at runtime.
|
||
 | ||
|
||
The content creation tools may either provide glTF directly, or use one of the open-source conversion utilities like [obj2gltf](https://github.com/AnalyticalGraphicsInc/obj2gltf) or [COLLADA2GLTF](https://github.com/KhronosGroup/glTF/tree/master/COLLADA2GLTF) to convert legacy formats to glTF. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we can imply that OBJ and COLLADA are legacy. They just serve a different purpose than glTF.
@@ -0,0 +1,111 @@ | |||
## The basic structure of glTF | |||
|
|||
The core of glTF is a JSON file. This file describes the whole contents of the 3D scene. It consists of a description of the scene structure itself, which is given by a hierarchy of nodes that define a scene graph. The 3D objects that appear in the scene are defined using meshes that are attached to the nodes. Animations describe how the 3D objects are transformed (e.g. rotated to translated) over time. Materials and textures define the appearance of the objects, and cameras describe the view configuration for the renderer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are also skins. Up to you if you think they are worth a mention here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Materials and textures" could just be "Materials" since materials imply techniques/textures/programs/shaders/etc. Really up to you.
|
||
 | ||
|
||
As shown in the image above, there are three types of objects that may contain such links to external resources, namely `buffers`, `images` and `shaders`. These objects will later be explained in more detail. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Skins too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I think buffers cover skins.
|
||
### Local and global transforms | ||
|
||
Each node can have a transform. Such a transform will usually define a translation, rotation or a scaling. This transform will be applied to all elements that are attached to the node itself and to all its child nodes. The hierarchy of nodes thus allows to structure the translations, rotations and scalings that are applied to the scene elements. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"usually define a translation, rotation or a scaling" -> "define a translation, rotation and/or scale"
```javascript | ||
"node0": { | ||
"matrix": [ | ||
0.0, 1.0, 2.0, 3.0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use this exact matrix; it is not an affine transform. Use a matrix where the bottom row is [0.0, 0.0, 0.0, 1.0]
and the top 3x3 matrix defines a trivial rotation and the rightmost 3x1 vector defines a trivial translation.
} | ||
``` | ||
|
||
This representation can be imagined as simply performing the transformations, one after the other. The `translation` just contains the translation in x-, y- and z-direction. The `scale` contains the scaling factors along the x-, y- and z-axis. The trickiest part is the `rotation`, which is given as a [quaternion](https://en.wikipedia.org/wiki/Quaternion). The mathematical background of quaternions is beyond the scope of this tutorial. For now, the most important information is that a quaternion is a compact representation of a rotation about an arbitrary angle and around an arbitrary axis. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest making this more precise, see KhronosGroup/glTF#743
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The subsequent section explained this in more detail, and emphasized the importance of computing the matrix as M=TRS. (In fact, I thought that KhronosGroup/glTF@eb4afea might have been caused by someone noticing this in the tutorial).
However, I can try to elaborate the TRS computation, maybe add concrete examples of simple T,R and S matrices, and try to explain that this will eventually be equivalent to scaling, then rotating, and then translating the vertices.
|
||
> In the old, fixed-function OpenGL, there have been the [`glOrtho`](https://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml) and [`gluPerspective`](https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml) functions that applied the matrices directly on top of the matrix stack. | ||
|
||
What may be important to note is that the camera itself in glTF is assumed to be in a "default" orientation. This is the same configuration that the camera has by default in OpenGL: The eye point of the camera is at the origin, and the viewing direction is along the negative z-axis. All transformations of the camera are only determined by the global transform of the `node` that refers to the camera. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe that glTF implies a default camera, e.g., here it kind of sounds like when we load a model we should move the camera to this default location.
@@ -0,0 +1,273 @@ | |||
# Scenes, nodes, cameras and animations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After reading this section, I suggest considering restructuring the tutorial. It seems like a reader would have to go through the entire tutorial in order to get started with glTF. This section, for examples, goes into animations (before accessors) and cameras, both of which are not needed to get started.
Perhaps it would be useful to restructure so that the initial goal is to build up to a minimal glTF asset (e.g., no cameras, materials, animations, etc), and then start adding complexity. As is, I don't know that the reader has enough context unless (1) they read the tutorial in its entirety or (2) they already have experience with glTF or another non-trivial 3D format.
|
||
### Mesh primitives | ||
|
||
The mesh itself usually does not have any properties, but only contains an array of [`meshPrimitive`](https://github.com/KhronosGroup/glTF/tree/master/specification#reference-mesh.primitive) objects. These `meshPrimitive` objects are smaller parts or building blocks of a larger object: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throughout meshPrimitive
-> mesh.primitive
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is related to point 3 of #5 - quoting:
Make the formatting (backticking) consistent. Should it be "The mesh contains a mesh primitive", or "The
mesh
contains ameshPrimitive
"? Which is considered more readable?
(Now with the additional aspect of mesh.primitive
instead of meshPrimitive
)
It may sound odd, but one of the main reasons for not backticking certain words for me was the plural: I think that accessor
s and mesh
es causes a pain in the eye, and always rephrasing this to "accessor
objects" and "mesh
objects" may also look strange after a while.
Maybe we can sort this out here once and for all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spec uses backticks throughout. I would probably do the same here. For plural, I usually do, for example, "accessor
objects." It's the best workaround I could come up with.
My main point was that meshPrimitive
is not in glTF; it is mesh.primitive
.
|
||
#### Mesh primitive attributes | ||
|
||
In order to render the geometry of a `meshPrimitive`, the information about *what* should be rendered and *how* it should be rendered has to be combined. The information about *what* should be rendered is given by the actual geometry information. This is at least a set of vertices and certain attributes that belong to the vertices. The `attributes` dictionary of the `meshPrimitive` contains references to `acessor` objects. An `accessor` is an abstract source of data, and in the simplest case it can be imagined as a block of memory, together with some information about the data type and layout of this memory block. In the example above, the `attributes` contain references to three `accessors`. These accessors describe the positions and normal vectors for the vertices of the mesh, and the texture coordinates at these vertices: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and above, "how" it should be rendered it mentioned a lot. That is vague; for example, it could mean materials.
Be precise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This explanation could potentially be clearer if, previously buffers, bufferViews, and accessors were introduced (in that order).
|
||
In order to render the geometry of a `meshPrimitive`, the information about *what* should be rendered and *how* it should be rendered has to be combined. The information about *what* should be rendered is given by the actual geometry information. This is at least a set of vertices and certain attributes that belong to the vertices. The `attributes` dictionary of the `meshPrimitive` contains references to `acessor` objects. An `accessor` is an abstract source of data, and in the simplest case it can be imagined as a block of memory, together with some information about the data type and layout of this memory block. In the example above, the `attributes` contain references to three `accessors`. These accessors describe the positions and normal vectors for the vertices of the mesh, and the texture coordinates at these vertices: | ||
|
||
 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be more clear to "flatten" each array and highlight, for example, 3 elements for a vec3; otherwise, it is not clear what the data structure is, e.g., is it an array of structs?
|
||
#### Mesh primitive indices | ||
|
||
The mesh primitive can also contain an accessor with the key name `indices`. This accessor provides the indices of the vertices that the mesh elements consist of. For example, when the rendering `mode` is `GL_TRIANGLES`, then three consecutive elements of the indices accessor are the vertex indices of one triangle. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could use more detail and should also emphasize that indices are used in almost all cases.
|
||
There are several well-known parameters that are commonly used to describe a material in OpenGL: | ||
|
||
* The "diffuse" color: The main color of the material, which is often defined by a texture |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"main" is not precise. Diffuse light scatters in all directions.
|
||
## Programs and Shaders | ||
|
||
The rendering process in OpenGL is described with small shader programs, which are written in [GLSL, the OpenGL shading language](https://www.opengl.org/documentation/glsl/). Such a shader program consists of at least two shaders, namely the vertex shader and the fragment shader. Roughly speaking, the vertex shader defines how the vertices of an object are transformed, preprocessed and projected on the screen, and the fragment shader defines how these projected vertices are used to fill the pixels on the screen to generate the final rendered image. For further details, refer to one of the GLSL tutorials (e.g. at [open.gl](https://open.gl/drawing#Shaders), [webglfundamentals.org](http://webglfundamentals.org/webgl/lessons/webgl-shaders-and-glsl.html) or others) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"preprocessed and projected on the screen"
I don't know what preprocessed means, and the vertices are not projected to the screen here.
Again, we should be precise.
The vertex shader transforms vertex positions from model coordinates to clip coordinates. This is also the stage were bone matrices will be blended for skinning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fragment shader determines the color (and potentially depth) of fragments. Fragments become pixels when they pass the depth test by the end of the frame.
The explanation above kind of sounds like rasterizations happens as part of the fragment shader.
|
||
 | ||
|
||
One can imagine that the vertex shader is executed for each vertex, and receives the attribute values for the respective vertex in the attribute variables. For example, the following vertex shader defines attributes for the position, normal and texture coordinate of each vertex: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider removing "One can imagine that"
|
||
void main(void) | ||
{ | ||
vec4 pos = u_modelViewMatrix * vec4(a_position,1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1
-> 1.0
I surprised this compiled.
Or consider defined a_position
as a vec4
and explain that the 1
is implicitly added when the input is vec3
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that I once encountered compilers complaining about 1.0
being double
, and demanding 1.0f
, but it might well be that I mixed something up here, and this was not in the context of GLSL, but OpenCL kernels...
However, I assume that 1.0
is a better practice here, and will review the GLSL spec also regarding the implicit 1
that you mentioned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC Some GLSL versions for desktop OpenGL implicitly convert 1
to float, but not WebGL. I know I've had shaders not compile in WebGL because of this...it could have been a while ago. Nonetheless, it is the recommended practice.
Update gltfTutorial_005_BuffersBufferViewsAccessors.md
Update gltfTutorial_007_Animations.md
The author used the term "transform" instead of "translation" when referring to the TRS components in the JSON file.
Added a minor fix to the 4th tutorial
Replaced broken anchor with "gltfTutorial_008_SimpleMeshes.md".
Minor fix of broken anchor to 8th tutorial
The byteStride was moved from the accessors to the bufferView
Update gltfTutorial_020_Skins.md
Additional cleanups for navigation links and README
@pjcozzi There have been some updates. I think that it should be largely consistent now (although I'll still have to do a "click-through" to check all the links). If there are no major issues left, I think that it could be merged soon. (BTW: For the Advanced Material section I re-used the WaterBottle image from the spec - I hope this is OK) The PR has been pending for quite a while now (too long, obviously - sorry about that). But I think that all further changes and restructurings should be based on the feedback from people who are actually using the tutorial to get a grip on glTF. @slchow Most of the changes have been in the sample snippets, to update them for 2.0. The main parts where new text was introduced for 2.0 are
|
Awesome, thanks @slchow! |
Copyedit
For sure! |
This is the first part of the generic glTF tutorial.
I will open some issues with points that still have to be discussed.