Skip to content

zixin96/gltf-webgpu-viewer

Repository files navigation


glTF 2.0 PBR Renderer - WebGPU

Zixin Zhang

Live demo Use Edge/Chrome Canary and enter the following to the address field:

For Edge:

  • edge://flags/#enable-unsafe-webgpu

For Chrome:

  • Chrome://flags/#enable-unsafe-webgpu

About The Project

glTF is not "yet another file format."

There are more than 70 different file formats for 3D data. Why do we need one more? glTF can significantly simplify the 3D content pipeline. Instead of implementing hundreds of importers and converters for various file formats, runtime applications only need to support glTF that is provided by custom converters such as obj2gltf.

WebGPU is an unreleased Javascript Graphics API with its own shading language called WGSL. However, this project uses GLSL as the shading language. @webgpu/glslang converts GLSL to SPIR-V so that it can be used on WebGPU.

This projects uses glTF-Transform, a glTF 2.0 SDK for TypeScript, to load glTF files from the web. With this SDK, we can easily query the data inside glTF without implementing the glTF loading structure from scratch.

It was quite an adventure to explore this new API and implement something really cool 😎.

Supported glTF Features

✅: fully supported

❗: partially supported (undesirable loading time)

Loading

  • Loading glTF and glb files (supported by gl-Transform) ✅

Core

  • Core glTF 2.0 Sample Models
Antique Camera✅ Avocado✅ Barramundi Fish✅
Boom Box✅ Corset✅ Damaged Helmet✅
Flight Helmet✅ Lantern✅ Sci Fi Helmet✅
Suzanne✅ Water Bottle✅

Standard

  • Standard glTF 2.0 Sample Models
    • Box ✅
    • Box Interleaved✅
    • Box Textured✅
    • Box Textured NPOT✅
    • Box With Spaces✅
    • Box Vertex Colors✅
    • Cube✅
    • Duck✅
    • 2 Cylinder Engine ❗
    • Reciprocating Saw ❗
    • Gearbox Assy ❗
    • Buggy ❗
    • Sponza❗
    • Two Sided Plane✅

Feature Tests

  • Feature Tests glTF 2.0 Sample Models
    • Boom Box With Axes ✅
    • TextureSettingsTest ✅

Extensions

  • KHR_lights_punctual ✅: 6 directional lights are used to light the scene.

Implementation Details

The simplified structure of the project can be summarized using the following graph:

Structure Figure 1: Simplified Structure

gl-Transform provides an easy-to-use interface (such as Doc, Root, Node, etc.) to access the data from glTF files. Only a single set of vertex and fragment shader is used. The functionality of the shaders is determined by #define preprocessor. These #defines are dynamically generated and inserted into the shaders. This is very similar to the shader architecture used in glTF-Sample-Viewer by KhronosGroup.

It is interesting to note that shaders used in WebGL cannot be used directly in the WebGPU pipeline, mostly due to the different uses of uniforms and textures. A comparison between GLSL, WGSL, and GLSL(WebGL) is shown below:

Shader Figure 2: Shader Languages Comparison

Major modifications will be needed to convert shaders used in WebGL to those in WebGPU. All uniforms need to be put in the uniform block and assigned a layout and binding, and all samplers are replaced by pairs of texture and sampler. The rest of the job is to carefully pass glTF data into the pipeline. Since primitives in a glTF file may use different shader programs, we need to use multiple pipelines to render multiple objects on the scene.

Getting Started

To test out this project:

  1. Clone the repo
  2. Install NPM packages and Use Chrome Canary to open a localhost
    npm start

(back to top)

Limitations

  • There are two reasons why I choose to use GLSL in this project:
  1. GLSL sits in the middle of the complexity diagram. It grants you more control over the rendering pipeline, but is less verbose than WGSL.
  2. GLSL can be manually converted to WGSL, without modifying the renderer code (since they all use the same concepts like binding and grouping).

However, adding an extra layer of conversion means that models with lots of primitives/meshes are loaded very slowly since the renderer creates and converts shaders per primitive. This is one of the disadvantages of using GLSL as the shading language.

glsl Figure 3: GLSL Issue
  • Most of the rendering codes are squeezed into a single file. Also, there are some obvious opportunities for refactoring due to my initial unfamiliarity with WebGPU. My future plan is to make the renderer more object-oriented for readability and refactor some repeating code to follow DRY principle.

(back to top)

Roadmap

  • Improve loading time of large models
  • Support more models from feature test
  • Support Animation and Skin
  • Support materials extensions such as transmission
  • Support for user camera
  • Make renderer more object-oriented and refactor repeating codes

(back to top)

Acknowledgments

Thank you for all the authors below for making this project possible.

(back to top)

Epilogue

  • If you use Webpack as the module bundler, remember to use development mode. Otherwise, class and variable names will not be properly displayed (i, S instead of class name, breakpoints not hit all the time)
  • Need at least #version 310 es to use glslang
  • Existing shaders in Khronos are NOT compatible with WebGPU. To make it work, we need to add layout and non-opaque uniforms.
  • The Map object holds key-value pairs and remembers the original insertion order of the keys.
  • Number of entries (3) did not match the number of entries (1) specified in [BindGroupLayout] If we declare uniform in the shader, we need to use them in the main() function.

About

glTF 2.0 PBR Renderer Using WebGPU

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published