Skip to content
Go to file

Latest commit

Fixes type error for vec3 vertex color inside vertex shader.

Git stats


Failed to load latest commit information.

glTF 2.0 Sample Viewer

This is the official Khronos glTF 2.0 sample viewer using WebGL: glTF 2.0 Sample Viewer

Table of Contents




Developed by UX3D and based on the former glTF-WebGL-PBR project. Supported by the Khronos Group and Facebook for animations, skinning and morphing.




Link to the live glTF 2.0 Sample Viewer.



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 selection list


  • Drag and drop glTF files into viewer


For local usage and debugging, please follow these instructions:

(0) Make sure Git LFS is installed.

(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.

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.


  • 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 choosing 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.

Appendix A: Metallic-Roughness Material

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

vec3 F_specular = D * Vis * F;
vec3 F_diffuse = (1.0 - F) * diffuse;
vec3 F = F_specular + F_diffuse;

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

Specular Term (F_specular)

Microfacet metallic-roughness BRDF

vec3 metallicBRDF (vec3 f0, vec3 f90, float alphaRoughness, float VdotH, float NdotL, float NdotV, float NdotH)
    vec3 F = fresnel(f0, f90, VdotH);
    float Vis = V_GGX(NdotL, NdotV, alphaRoughness);
    float D = D_GGX(NdotH, alphaRoughness);

    return F * Vis * D;

Surface Reflection Ratio (F)

Fresnel Schlick

vec3 fresnel(vec3 f0, vec3 f90, float VdotH)
    return f0 + (f90 - f0) * pow(clamp(1.0 - 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 / Visibility (V)

Smith Joint GGX

float V_GGX(float NdotL, float NdotV, float alphaRoughness)
    float alphaRoughnessSq = alphaRoughness * alphaRoughness;

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

    float GGX = GGXV + GGXL;
    if (GGX > 0.0)
        return 0.5 / GGX;
    return 0.0;

Normal Distribution (D)

Trowbridge-Reitz GGX

float D_GGX(float NdotH, float alphaRoughness)
    float alphaRoughnessSq = alphaRoughness * alphaRoughness;
    float f = (NdotH * NdotH) * (alphaRoughnessSq - 1.0) + 1.0;
    return alphaRoughnessSq / (M_PI * f * f);

Diffuse Term (F_diffuse)


vec3 lambertian(vec3 f0, vec3 f90, vec3 diffuseColor, float VdotH)
    return (1.0 - fresnel(f0, f90, VdotH)) * (diffuseColor / M_PI);

Appendix B: FAQ

Q: Why do I not see environment lighting here
A: The glTF Sample Viewer is using KTX2 for the pre-filtered environments. However, the mime type is not yet registered here.


Physically-Based Rendering in glTF 2.0 using WebGL




No packages published
You can’t perform that action at this time.