Documentation for Substance 3D Painter is now available on Experience League. After March 14th, HelpX pages will automatically redirect to the equivalent Experience League page.
Refer to the FAQ for more information about which documentation is affected.
- Substance 3D home
- Home
- Getting Started
- Getting Started overview
- Activation and licenses
- System requirements
- Project creation
- Export
- Export overview
- Export window
- Output templates
- Export overview
- Glossary
- Getting Started overview
- Interface
- Interface overview
- Assets
- Substance 3D Assets
- Color picker
- Display settings
- History
- Layer stack
- Main menu
- Project configuration
- Properties
- Settings
- Shader settings
- Texture Set
- Toolbars
- Viewport
- Miscellaneous
- Painting
- Painting overview
- Paint tools
- Path tools
- Path tool overview
- Paint along path
- Ribbon path
- Filled path
- Erase along path
- Smudge along path
- Straight line
- Lazy mouse
- Symmetry
- Fill projections
- Presets
- Presets overview
- Creating and saving presets
- Creating particles presets
- Photoshop brush presets
- Dynamic strokes
- Advanced channel painting
- Vector graphic (.svg & .ai)
- Text resource
- Effects
- Baking
- Content
- Creating custom effects
- Importing assets
- Creating custom effects
- Features
- Automatic resource update
- 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 11.1
- Version 11.0
- Version 10.1
- Known issues
- Old versions
- Version 10.0
- Version 9.1
- 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 Sampler - Shader API
lib-sampler.glsl
Public Functions: getAO getShadowFactor getGlossiness getRoughness getMetallic getAnisotropyLevel getAnisotropyAngle getOpacity getHeight getDisplacement getSpecularLevel getBaseColor getDiffuse getSpecularColor getScattering generateAnisotropicRoughness generateDiffuseColor generateSpecularColor
Import from library
import lib-defines.glsl import lib-sparse.glsl
Default background colors when there is no data in channel (alpha is 0)
const vec3 DEFAULT_BASE_COLOR = vec3(0.5); const float DEFAULT_ROUGHNESS = 0.3; const float DEFAULT_METALLIC = 0.0; const float DEFAULT_ANISOTROPY_LEVEL = 0.0; const float DEFAULT_ANISOTROPY_ANGLE = 0.0; const float DEFAULT_OPACITY = 1.0; const float DEFAULT_AO = 1.0; const float DEFAULT_SPECULAR_LEVEL = 0.5; const float DEFAULT_HEIGHT = 0.0; const float DEFAULT_DISPLACEMENT = 0.0; const float DEFAULT_SCATTERING = 0.0;
AO map.
//: param auto ao_blending_mode uniform int ao_blending_mode; //: param auto texture_ao uniform SamplerSparse base_ao_tex; //: param auto channel_ao uniform SamplerSparse ao_tex;
A value used to tweak the Ambient Occlusion intensity.
//: param custom {
//: "default": 0.75,
//: "label": "AO Intensity",
//: "min": 0.00,
//: "max": 1.0,
//: "group": "Common Parameters"
//: }
uniform float ao_intensity;
Shadowmask.
//: param auto shadow_mask_enable uniform bool sm_enable; //: param auto shadow_mask_opacity uniform float sm_opacity; //: param auto shadow_mask uniform sampler2D sm_tex; //: param auto screen_size uniform vec4 screen_size;
Return sampled glossiness or a default value
float getGlossiness(vec4 sampledValue)
{
return sampledValue.r + (1.0 - DEFAULT_ROUGHNESS) * (1.0 - sampledValue.g);
}
float getGlossiness(SamplerSparse sampler, SparseCoord coord)
{
return getGlossiness(textureSparse(sampler, coord));
}
Return sampled roughness or a default value
float getRoughness(vec4 sampledValue)
{
return sampledValue.r + DEFAULT_ROUGHNESS * (1.0 - sampledValue.g);
}
float getRoughness(SamplerSparse sampler, SparseCoord coord)
{
return getRoughness(textureSparse(sampler, coord));
}
Return sampled metallic or a default value
float getMetallic(vec4 sampledValue)
{
return sampledValue.r + DEFAULT_METALLIC * (1.0 - sampledValue.g);
}
float getMetallic(SamplerSparse sampler, SparseCoord coord)
{
return getMetallic(textureSparse(sampler, coord));
}
Return sampled anisotropy level or a default value
float getAnisotropyLevel(vec4 sampledValue)
{
return sampledValue.r + DEFAULT_ANISOTROPY_LEVEL * (1.0 - sampledValue.g);
}
float getAnisotropyLevel(SamplerSparse sampler, SparseCoord coord)
{
return getAnisotropyLevel(textureSparse(sampler, coord));
}
Return sampled anisotropy angle or a default value
float getAnisotropyAngle(vec4 sampledValue)
{
return M_2PI * (sampledValue.r + DEFAULT_ANISOTROPY_ANGLE * (1.0 - sampledValue.g));
}
float getAnisotropyAngle(SamplerSparse sampler, SparseCoord coord)
{
// Manual trilinear filtering
float level = max(0.0, textureSparseQueryLod(sampler, coord) + uvtile_lod_bias);
int level0 = int(level);
int level1 = level0 + 1;
ivec2 texSize0 = ivec2(sampler.size.xy) >> level0;
ivec2 texSize1 = texSize0 >> 1;
ivec2 itex_coord0 = ivec2(coord.tex_coord * vec2(texSize0));
ivec2 itex_coord1 = ivec2(coord.tex_coord * vec2(texSize1));
// Assuming tex sizes are pow of 2, we can do the fast modulo
ivec2 texSizeMask0 = texSize0 - ivec2(1);
ivec2 texSizeMask1 = texSize1 - ivec2(1);
// Fetch the 8 samples needed
float a000 = getAnisotropyAngle(texelFetch(sampler.tex, itex_coord0 & texSizeMask0, level0));
float a001 = getAnisotropyAngle(texelFetch(sampler.tex, (itex_coord0 + ivec2(1, 0)) & texSizeMask0, level0)) - a000;
float a010 = getAnisotropyAngle(texelFetch(sampler.tex, (itex_coord0 + ivec2(0, 1)) & texSizeMask0, level0)) - a000;
float a011 = getAnisotropyAngle(texelFetch(sampler.tex, (itex_coord0 + ivec2(1, 1)) & texSizeMask0, level0)) - a000;
float a100 = getAnisotropyAngle(texelFetch(sampler.tex, itex_coord1 & texSizeMask1, level1)) - a000;
float a101 = getAnisotropyAngle(texelFetch(sampler.tex, (itex_coord1 + ivec2(1, 0)) & texSizeMask1, level1)) - a000;
float a110 = getAnisotropyAngle(texelFetch(sampler.tex, (itex_coord1 + ivec2(0, 1)) & texSizeMask1, level1)) - a000;
float a111 = getAnisotropyAngle(texelFetch(sampler.tex, (itex_coord1 + ivec2(1, 1)) & texSizeMask1, level1)) - a000;
// Detect if the angle warps inside the filtering footprint, and fix it
a001 += abs(a001) > M_PI ? sign(a001) * -M_2PI + a000 : a000;
a010 += abs(a010) > M_PI ? sign(a010) * -M_2PI + a000 : a000;
a011 += abs(a011) > M_PI ? sign(a011) * -M_2PI + a000 : a000;
a100 += abs(a100) > M_PI ? sign(a100) * -M_2PI + a000 : a000;
a101 += abs(a101) > M_PI ? sign(a101) * -M_2PI + a000 : a000;
a110 += abs(a110) > M_PI ? sign(a110) * -M_2PI + a000 : a000;
a111 += abs(a111) > M_PI ? sign(a111) * -M_2PI + a000 : a000;
// Trilinear blending of the samples
vec2 t0 = coord.tex_coord * vec2(texSize0) - vec2(itex_coord0);
vec2 t1 = coord.tex_coord * vec2(texSize1) - vec2(itex_coord1);
return mix(
mix(mix(a000, a001, t0.x), mix(a010, a011, t0.x), t0.y),
mix(mix(a100, a101, t1.x), mix(a110, a111, t1.x), t1.y),
level - float(level0));
}
Return sampled opacity or a default value
float getOpacity(vec4 sampledValue)
{
return sampledValue.r + DEFAULT_OPACITY * (1.0 - sampledValue.g);
}
float getOpacity(SamplerSparse sampler, SparseCoord coord)
{
return getOpacity(textureSparse(sampler, coord));
}
Return sampled height or a default value
float getHeight(vec4 sampledValue)
{
return sampledValue.r + DEFAULT_HEIGHT * (1.0 - sampledValue.g);
}
float getHeight(SamplerSparse sampler, SparseCoord coord)
{
return getHeight(textureSparse(sampler, coord));
}
Return sampled displacement or a default value
float getDisplacement(vec4 sampledValue)
{
return sampledValue.r + DEFAULT_DISPLACEMENT * (1.0 - sampledValue.g);
}
float getDisplacement(SamplerSparse sampler, SparseCoord coord)
{
return getDisplacement(textureSparse(sampler, coord));
}
Return ambient occlusion
float getAO(SparseCoord coord, bool is_premult)
{
vec2 ao_lookup = textureSparse(base_ao_tex, coord).ra;
float ao = ao_lookup.x + DEFAULT_AO * (1.0 - ao_lookup.y);
if (ao_tex.is_set) {
ao_lookup = textureSparse(ao_tex, coord).rg;
if (!is_premult) ao_lookup.x *= ao_lookup.y;
float channel_ao = ao_lookup.x + DEFAULT_AO * (1.0 - ao_lookup.y);
if (ao_blending_mode == BlendingMode_Replace) {
ao = channel_ao;
} else if (ao_blending_mode == BlendingMode_Multiply) {
ao *= channel_ao;
}
}
// Modulate AO value by AO_intensity
return mix(1.0, ao, ao_intensity);
}
Helper to get ambient occlusion for shading
float getAO(SparseCoord coord)
{
return getAO(coord, true);
}
Return specular level
float getSpecularLevel(vec4 sampledValue)
{
return sampledValue.r + DEFAULT_SPECULAR_LEVEL * (1.0 - sampledValue.g);
}
float getSpecularLevel(SamplerSparse sampler, SparseCoord coord)
{
return getSpecularLevel(textureSparse(sampler, coord));
}
Fetch the shadowing factor (screen-space)
float getShadowFactor()
{
float shadowFactor = 1.0;
if (sm_enable) {
vec2 screenCoord = (gl_FragCoord.xy * vec2(screen_size.z, screen_size.w));
vec2 shadowSample = texture(sm_tex, screenCoord).xy;
// shadowSample.x / shadowSample.y is the normalized shadow factor.
// shadowSample.x may already be normalized, shadowSample.y contains 0.0 in this case.
shadowFactor = shadowSample.y == 0.0 ? shadowSample.x : shadowSample.x / shadowSample.y;
}
return mix(1.0, shadowFactor, sm_opacity);
}
Return sampled base color or a default value
vec3 getBaseColor(vec4 sampledValue)
{
return sampledValue.rgb + DEFAULT_BASE_COLOR * (1.0 - sampledValue.a);
}
vec3 getBaseColor(SamplerSparse sampler, SparseCoord coord)
{
return getBaseColor(textureSparse(sampler, coord));
}
Return sampled diffuse color or a default value
vec3 getDiffuse(vec4 sampledValue)
{
return getBaseColor(sampledValue);
}
vec3 getDiffuse(SamplerSparse sampler, SparseCoord coord)
{
return getDiffuse(textureSparse(sampler, coord));
}
Return sampled specular color or a default value
vec3 getSpecularColor(vec4 sampledValue)
{
vec3 specColor = sampledValue.rgb + DEFAULT_BASE_COLOR * (1.0 - sampledValue.a);
vec3 defaultF0 = mix(vec3(0.04), specColor, DEFAULT_METALLIC);
return mix(specColor, defaultF0, (1.0 - sampledValue.a));
}
vec3 getSpecularColor(SamplerSparse sampler, SparseCoord coord)
{
return getSpecularColor(textureSparse(sampler, coord));
}
Generate anisotropic roughness from roughness and anisotropy level
vec2 generateAnisotropicRoughness(float roughness, float anisoLevel)
{
return vec2(roughness, roughness / sqrt(max(1e-8, 1.0 - anisoLevel)));
}
Generate diffuse color from base color and metallic factor
vec3 generateDiffuseColor(vec3 baseColor, float metallic)
{
return baseColor * (1.0 - metallic);
}
Generate specular color from dielectric specular level, base color and metallic factor
vec3 generateSpecularColor(float specularLevel, vec3 baseColor, float metallic)
{
return mix(vec3(0.08 * specularLevel), baseColor, metallic);
}
Generate specular color from base color and metallic factor, using default specular level (0.04) for dielectrics
vec3 generateSpecularColor(vec3 baseColor, float metallic)
{
return mix(vec3(0.04), baseColor, metallic);
}
Return sampled scattering value or a default value
float getScattering(vec4 sampledValue)
{
return sampledValue.r + DEFAULT_SCATTERING * (1.0 - sampledValue.g);
}
float getScattering(SamplerSparse sampler, SparseCoord coord)
{
return getScattering(textureSparse(sampler, coord));
}