Skip to content
Physically-Based Rendering in glTF 2.0 using WebGL
Branch: master
Clone or download
Latest commit 46c8a10 Apr 17, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
.vscode Add recommended extensions Apr 12, 2019
assets Minor optimization in shader code. Referenceing glTF for BRDF. Apr 4, 2019
electron Add animation index and time point parameter to headless renderer Mar 6, 2019
libs Refactored and simplified code. Feb 7, 2019
src Merge pull request #203 from TimvanScherpenzeel/add-aces-tonemapping Apr 17, 2019
.eslintignore Include electron folder, exclude rollup.config.js Apr 12, 2019
.gitattributes Tweak comment Apr 12, 2019
.gitignore added yarn lock file to .gitignore, in line with ignored package-lock… Apr 16, 2019
.project Switched to standard Khronos Apache License. Mar 8, 2019 Changed Reference to Sample Apr 16, 2019
headless.html Renames from reference to sample. Apr 17, 2019
index.html Renames from reference to sample. Apr 17, 2019
index_field.html Renames from reference to sample. Apr 17, 2019
index_papermill.html Renames from reference to sample. Apr 17, 2019
index_pisa.html Renames from reference to sample. Apr 17, 2019
package.json Renames from reference to sample. Apr 17, 2019
rollup.config.js Include axios as a dependency. Dec 14, 2018
styles.css Added spinner for loading glTF files. Added model index for models/ i… Oct 30, 2018

glTF 2.0 Sample Viewer

This is the offical Khronos glTF 2.0 sample viewer using WebGL.

Table of Contents



If you would like to see this in action, view the live demo.


click + drag : Rotate model

scroll : Zoom camera

GUI : Use to change models and settings

Change glTF model

  • Choose one of the glTF models in the selction list


  • Drag and drop glTF files into viewer

Offline / Headless Rendering

NOTE: The dimensions of the rendered image are limited by the (virtual) desktop size.


Configure environment

  • npm install (also installs Electron)
  • npm run build (“compile” the code)


  • npm run start-offscreen -- -- -h for a list of available options


  • npm run start-offscreen -- -- assets\models\2.0\FlightHelmet\glTF\FlightHelmet.gltf

After execution, the screenshot is stored as output.png on the file system.


For local usage and debugging, please follow these instructions:

(1) Checkout the master branch

(2) Install dependencies with npm install

(3) Pull the submodules for the required glTF sample models and environments git submodule update --init --recursive

(4a) Start a demo in the browser with npm run dev, and open http://localhost:8000.

(4b) Start a demo in Electron with npm run dev:electron.

When making changes, the project is automatically rebuilt and the dist/ folder is updated. Files in the dist/ folder should not be included in pull requests — they will be updated by project maintainers with each new release.


  • Requirements
  • Install the Debugger for Firefox extension for Visual Studio Code
  • Open the project folder in Visual Studio Code and select Debug->Add Configuration->Firefox so the .vscode/launch.json file is created.
  • Debug->Start Debugging should now launch a Firefox window with the sample viewer and VS Code breakpoints should be hit.

Physically-Based Materials in glTF 2.0

With the change from glTF 1.0 to glTF 2.0, one of the largest changes included core support for materials that could be used for physically-based shading. Part of this process involved chosing technically accurate, yet user-friendly, parameters for which developers and artists could use intuitively. This resulted in the introduction of the Metallic-Roughness Material to glTF. If you would like to read more about glTF, you can find the content at its GitHub page.

A good reference about Physically-Based Materials and its workflow can be found on the THE PBR GUIDE - PART 1 and THE PBR GUIDE - PART 2 from allegorithmic.

For implementation details and further theory, please find more information in the Real Shading in Unreal Engine 4 presentation from the SIGGRAPH 2013 course.


For further reference, please read the glTF 2.0: Appendix B: BRDF Implementation
The following sections do summarize the important shader code.

vec3 specularContribution = D * Vis * G;
vec3 diffuseContribution = (1.0 - F) * diffuse; 

Please note: Vis = G / (4 * NdotL * NdotV)

Specular Term

Microfaced Distribution (D)

Trowbridge-Reitz GGX

float microfacetDistribution(MaterialInfo materialInfo, AngularInfo angularInfo)
    float alphaRoughnessSq = materialInfo.alphaRoughness * materialInfo.alphaRoughness;
    float f = (angularInfo.NdotH * alphaRoughnessSq - angularInfo.NdotH) * angularInfo.NdotH + 1.0;
    return alphaRoughnessSq / (M_PI * f * f);

Surface Reflection Ratio (F)

Fresnel Schlick

vec3 specularReflection(MaterialInfo materialInfo, AngularInfo angularInfo)
    return materialInfo.reflectance0 + (materialInfo.reflectance90 - materialInfo.reflectance0) * pow(clamp(1.0 - angularInfo.VdotH, 0.0, 1.0), 5.0);

Please note, that the above shader code includes the optimization for "turning off" the Fresnel edge brightening (see "Real-Time Rendering" Fourth Edition on page 325).

Geometric Occlusion (G)

Smith Joint GGX

float visibilityOcclusion(MaterialInfo materialInfo, AngularInfo angularInfo)
    float NdotL = angularInfo.NdotL;
    float NdotV = angularInfo.NdotV;
    float alphaRoughnessSq = materialInfo.alphaRoughness * materialInfo.alphaRoughness;

    float GGXV = NdotL * sqrt(NdotV * NdotV * (1.0 - alphaRoughnessSq) + alphaRoughnessSq);
    float GGXL = NdotV * sqrt(NdotL * NdotL * (1.0 - alphaRoughnessSq) + alphaRoughnessSq);

    return 0.5 / (GGXV + GGXL);

Diffuse Term


vec3 diffuse(MaterialInfo materialInfo)
    return materialInfo.diffuseColor / M_PI;


  • glTF 2.0
  • KHR_lights_punctual extension
  • KHR_materials_pbrSpecularGlossiness
  • KHR_materials_unlit extension
  • KHR_texture_transform extension
You can’t perform that action at this time.