This blog post is a part of series about implementing PBR in WebGL from scratch:
PBR is a set of techniques aiming at improving realism of rendered graphics by using more physically correct formulas on how surfaces interact with light. Sometimes, especially in the realtime context it's called Physically Based Shading - PBS.
Compared to the old-school Ambient + Lambert Diffuse + Specular Blinn-Phong that you might know from OpenGL 1.0/2.0 era and first WebGL 1.0 engines, PBR brings a promise of the following benefits:
Unified shader being able to express wide range of materials from ceramics, wood and iron to sci-fi aluminum, chrome and plastic.
Predicable look under different lighting conditions.
We will cover this in more details in the future but in PBR we divide our materials into two main types:
Dielectrics / insulators (from plastic to rubber) - medium to very low reflectivity, base color due to reflected diffuse light
Metals / conductors (from silver to brushed aluminium) - highly reflective, no base color as they absorb the light, optional tint (e.g. gold)
Albedo, direct light diffuse, fresnel, diffuse reflection, specular reflection, final composition. More on this in the future as not everything here is 100% correct (e.g. I'm not completely sure about Fresnel)
WARNING:
- these demos are big, between 10-20MB = fidlots of staring at a black screen, please be patient and watch your JavaScript dev console logs
- should work on any major browser Chrome, Safari, Firefox both on Windows and on OSX
- it doesn't work on FF/OSX due to these bugs
- currently doesn't work on iOS as I didn't support texture HALF_FLOAT
- it hasn't been tested on Android
Materials (Click for the realtime version)
Material mixing (Click for the realtime version)
Exposure (Click for the realtime version)
NOPE. Sorry. Please continue reading to find out why.
In the last 1.5 years I've implemented 2-3 versions of PBR in the last year with a varying success due to complexity and amount of supporting engine code they require. They are also custom, per-project built tools and therefore often no publishable online. And the code is a mess.
Learning about all that stuff is a pain. Most talks assume you just finished writing your own renderer and know all the math or you are just upgrading your engine with some new tricks and techniques. I haven't really found a A-Z description of how to put all these pieces to together in code.
So the idea is that through the series of blog posts I reimplement PBR with a better understanding of the math involved and document the process.
- learn the math properly
- fix the mess above
- share runnable code implementing these ideas
- spread the NPM love and publish reusable parts as node modules
- write clean documented code with embedded math formulas so we know where are we
//this is shader code
//Normal Distribution Function: GGX
// a^2
//D(h) = --------------------------------
// PI * ((n.h)^2 * (a^2 - 1) + 1)^2
float aSqr = a * a;
float Ddenom = dotNH * dotNH * (aSqr - 1.0) + 1.0;
float Dh = aSqr / ( PI * Ddenom * Ddenom);
What's complexity you would ask? Let's try to list things that we should understand or at least know about and probably implement at some point:
- pbr workflows
- specular vs metallic
- albedo, glossines, roughes, specular, ao, cavity
- metals and dielectrics
- lighting models
- image base lighting
- irradiance environment map (IEM)
- prefiltered mipmaped radiance environment map (PMREM)
- spherical harmonics
- uber shaders (tried all three approaches)
- string concatenation
- ifdef code switches
- glslify modules
- texture loading
- hdr
- dds
- cubemap atlasses
- octagonal env maps
- color
- gamma correction
- linear space
- hdr
- tonemapping
- lighting
- brdfs
- energy conservation
- fresnel
- how IBL fits here
- area lights
- bump mapping
- tri planar texturing for generative shapes (used in the demos)
In the next blog post I'll setup the code base, cover some basics like HDR, tonemapping and gamma to prepare us for Image Based Lighting.
In the meantime you might want to check out some other material covering the topic:
Blogs
- PBR in JMonkeyEngine: I - PBR for Artists, II - PBR for Developers, III - IBL
- Marmoset: Basic Theory of Physically-Based Rendering, Physically Based Rendering, And You Can Too!, PBR Texture Conversion
Presentations
- Unity Physically Based Shading
- Real Shading in Unreal Engine 4 + Notes
- Crafting a Next-Gen Material Pipeline for The Order: 1886 + Notes
- SIGGRAPH 2013 Course Physically Based Shading in Theory and Practice
PBR Books
Open source engines implementing PBR
- 2D material textures come from http://gametextures.com [ License ]
- Environmental cubemaps come from Mr F filtered using Modified AMD CubemapGen based on Paul Debevec IBL Probes