Last updated on
Jul 13, 2023
- Substance 3D home
- Home
- Getting Started
- Getting Started overview
- Activation and licenses
- System requirements
- Project creation
- Export
- Export overview
- Export window
- Export presets
- Export overview
- Glossary
- Performance
- Getting Started overview
- Interface
- Assets
- Substance 3D Assets
- Color picker
- Display settings
- History
- Layer stack
- Main menu
- Project configuration
- Properties
- Settings
- Shader settings
- Texture Set
- Toolbars
- Viewport
- Miscellaneous
- Assets
- Painting
- Painting overview
- Tool list
- Straight line
- Lazy mouse
- Symmetry
- Fill projections
- Presets
- Presets overview
- Creating and saving presets
- Creating particles presets
- Photoshop brush presets (ABR)
- Dynamic strokes
- Advanced channel painting
- Vector graphic (.svg & .ai)
- Text resource
- Effects
- Baking
- Content
- Creating custom effects
- Importing assets
- Creating custom effects
- Features
- Automatic UV Unwrapping
- Physical size
- Smart Materials and Masks
- Subsurface Scattering
- Dynamic Material Layering
- UV Reprojection
- UV Tiles
- Color Management
- Post Processing
- Iray Renderer
- Plugins
- Sparse Virtual Textures
- Custom Shaders
- SpaceMouse® by 3Dconnexion
- Universal Scene Description (USD)
- Send to
- Technical Support
- Performance Guidelines
- Configuring Pens and Tablets
- Exporting the log file
- Exporting a DXDiag
- Technical issues
- GPU Issues
- Crash when working with overclocked GPU
- Forcing the external GPU on Mac OS
- GPU drivers compatibility
- GPU drivers crash with long computations (TDR crash)
- GPU has outdated drivers
- GPU is not recognized
- GPU is not recognized and is mentionned as GDI Generic
- Issues with Nvidia GPUs on recent Mac OS versions
- Multi/Bi-GPU
- Running on integrated GPU
- Painter doesn't start on the right GPU
- Startup Issues
- Rendering Issues
- Stability Issues
- Miscellaneous Issues
- GPU Issues
- Workflow Issues
- Export Issues
- Tools Issues
- Project Issues
- Library Issues
- Viewport Issues
- Plugins Issues
- License Issues
- Pipeline and integration
- Installation and preferences
- Configuration
- Resource management
- Scripting and development
- Scripts and plugins
- Shader API Reference
- Shader API overview
- Changelog - Shader API
- Libraries - Shader API
- Lib Alpha - Shader API
- Lib Bayer - Shader API
- Lib Defines - Shader API
- Lib Emissive - Shader API
- Lib Env - Shader API
- Lib Normal - Shader API
- Lib PBR - Shader API
- Lib PBR Aniso - Shader API
- Lib Pom - Shader API
- Lib Random - Shader API
- Lib Sampler - Shader API
- Lib Sparse - Shader API
- Lib SSS - Shader API
- Lib Utils - Shader API
- Lib Vectors - Shader API
- Parameters - Shader API
- Shaders - Shader API
- Release notes
- Release notes overview
- All Changes
- Version 10.1
- Version 10.0
- Version 9.1
- Old versions
- Version 9.0
- Version 8.3
- Version 8.2
- Version 8.1
- Version 7.4
- Version 7.3
- Version 7.2
- Version 2021.1 (7.1.0)
- Version 2020.2 (6.2.0)
- Version 2020.1 (6.1.0)
- Version 2019.3
- Version 2019.2
- Version 2019.1
- Version 2018.3
- Version 2018.2
- Version 2018.1
- Version 2017.4
- Version 2017.3
- Version 2017.2
- Version 2017.1
- Version 2.6
- Version 2.5
- Version 2.4
- Version 2.3
- Version 2.2
Lib PBR - Shader API
lib-pbr.glsl
Public Functions: normal_distrib fresnel G1 visibility horizonFading pbrComputeDiffuse pbrComputeSpecular pbrComputeBRDF
Number of miplevels in the envmap.
//: param auto environment_max_lod uniform float maxLod;
An int representing the number of samples made for specular contribution computation. The more the higher quality and the performance impact.
//: param custom { //: "default": 16, //: "label": "Quality", //: "widget": "combobox", //: "values": { //: "Very low (4 spp)": 4, //: "Low (16 spp)": 16, //: "Medium (32 spp)": 32, //: "High (64 spp)": 64, //: "Very high (128 spp)": 128, //: "Ultra (256 spp)": 256 //: }, //: "group": "Common Parameters" //: } uniform int nbSamples;
Value used to control specular reflection leaking through the surface.
//: param custom { //: "default": 1.3, //: "label": "Horizon Fading", //: "min": 0.0, //: "max": 2.0, //: "group": "Common Parameters" //: } uniform float horizonFade;
Import from library, other parameters
import lib-env.glsl import lib-emissive.glsl import lib-random.glsl import lib-vectors.glsl
BRDF related functions
const float EPSILON_COEF = 1e-4; float normal_distrib( float ndh, float Roughness) { // use GGX / Trowbridge-Reitz, same as Disney and Unreal 4 // cf http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p3 float alpha = Roughness * Roughness; float tmp = alpha / max(1e-8,(ndh*ndh*(alpha*alpha-1.0)+1.0)); return tmp * tmp * M_INV_PI; } vec3 fresnel( float vdh, vec3 F0) { // Schlick with Spherical Gaussian approximation // cf http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p3 float sphg = exp2((-5.55473*vdh - 6.98316) * vdh); return F0 + (vec3(1.0) - F0) * sphg; } float G1( float ndw, // w is either Ln or Vn float k) { // One generic factor of the geometry function divided by ndw // NB : We should have k > 0 return 1.0 / ( ndw*(1.0-k) + k ); } float visibility( float ndl, float ndv, float Roughness) { // Schlick with Smith-like choice of k // cf http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p3 // visibility is a Cook-Torrance geometry function divided by (n.l)*(n.v) float k = max(Roughness * Roughness * 0.5, 1e-5); return G1(ndl,k)*G1(ndv,k); } vec3 cook_torrance_contrib( float vdh, float ndh, float ndl, float ndv, vec3 Ks, float Roughness) { // This is the contribution when using importance sampling with the GGX based // sample distribution. This means ct_contrib = ct_brdf / ggx_probability return fresnel(vdh,Ks) * (visibility(ndl,ndv,Roughness) * vdh * ndl / ndh ); } vec3 importanceSampleGGX(vec2 Xi, vec3 T, vec3 B, vec3 N, float roughness) { float a = roughness*roughness; float cosT = sqrt((1.0-Xi.y)/(1.0+(a*a-1.0)*Xi.y)); float sinT = sqrt(1.0-cosT*cosT); float phi = 2.0*M_PI*Xi.x; return T * (sinT*cos(phi)) + B * (sinT*sin(phi)) + N * cosT; } float probabilityGGX(float ndh, float vdh, float Roughness) { return normal_distrib(ndh, Roughness) * ndh / (4.0*vdh); } float distortion(vec3 Wn) { // Computes the inverse of the solid angle of the (differential) pixel in // the cube map pointed at by Wn float sinT = sqrt(1.0-Wn.y*Wn.y); return sinT; } float computeLOD(vec3 Ln, float p) { return max(0.0, (maxLod-1.5) - 0.5 * log2(float(nbSamples) * p * distortion(Ln))); }
Horizon fading trick from https://marmosetco.tumblr.com/post/81245981087
float horizonFading(float ndl, float horizonFade) { float horiz = clamp(1.0 + horizonFade * ndl, 0.0, 1.0); return horiz * horiz; }
Compute the lambertian diffuse radiance to the viewer's eye
vec3 pbrComputeDiffuse(vec3 normal, vec3 diffColor) { return envIrradiance(normal) * diffColor; }
Compute the microfacets specular reflection to the viewer's eye
vec3 pbrComputeSpecular(LocalVectors vectors, vec3 specColor, float roughness) { vec3 radiance = vec3(0.0); float ndv = dot(vectors.eye, vectors.normal); for(int i=0; i<nbSamples; ++i) { vec2 Xi = fibonacci2D(i, nbSamples); vec3 Hn = importanceSampleGGX( Xi, vectors.tangent, vectors.bitangent, vectors.normal, roughness); vec3 Ln = -reflect(vectors.eye,Hn); float fade = horizonFading(dot(vectors.vertexNormal, Ln), horizonFade); float ndl = dot(vectors.normal, Ln); ndl = max( 1e-8, ndl ); float vdh = max(1e-8, dot(vectors.eye, Hn)); float ndh = max(1e-8, dot(vectors.normal, Hn)); float lodS = roughness < 0.01 ? 0.0 : computeLOD(Ln, probabilityGGX(ndh, vdh, roughness)); radiance += fade * envSampleLOD(Ln, lodS) * cook_torrance_contrib(vdh, ndh, ndl, ndv, specColor, roughness); } // Remove occlusions on shiny reflections radiance /= float(nbSamples); return radiance; }