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));

}
recommendation-more-help
4517c71e-0531-47f5-b14d-d3b9de4d0104