この記事について
- ゲーム向けの PBS で軽めの処理でなんとなくのエネルギー保存をする方法の事例です.
The Order 1886
// "Crafting a Next-Gen Material Pipeline for The Order: 1886" SIGGRAPH 2013
float RadDiffuse( float dot_v_h )
{
// 1.0 - F(VoH)
float value = 1.0 - pow( 1.0 - dot_v_h, 5.0 );
value *= INV_MATH_PI;
return value;
}
float F_d = RadDiffuse( dot_v_h );
vec3 diffuse_brdf = F_d * diffuse_color;
// Program Files\Allegorithmic\Substance Player\5\resources\view3d\shaders\physically_metallic_roughness\fs.glsl
float dielectricSpec = 0.08 * texture2D(specularLevel,uv).r;
vec3 dielectricColor = vec3(dielectricSpec, dielectricSpec, dielectricSpec);
vec3 diffColor = baseColor * (1.0 - metallic);
vec3 specColor = mix(dielectricColor, baseColor, metallic);
// Program Files\Allegorithmic\Substance Player\5\resources\view3d\shaders\common\pbr_ibl.glsl
diffColor *= ( vec3(1.0,1.0,1.0 ) - specColor ) );
Unity 5.4 beta 24
// From UnityStandardConfig.cginc
// Energy conservation for Specular workflow is Monochrome. For instance: Red metal will make diffuse Black not Cyan
#ifndef UNITY_CONSERVE_ENERGY
#define UNITY_CONSERVE_ENERGY 1
#endif
#ifndef UNITY_CONSERVE_ENERGY_MONOCHROME
#define UNITY_CONSERVE_ENERGY_MONOCHROME 1
#endif
// From UnityStandardUtils.cginc
// Diffuse/Spec Energy conservation
inline half3 EnergyConservationBetweenDiffuseAndSpecular (half3 albedo, half3 specColor, out half oneMinusReflectivity)
{
oneMinusReflectivity = 1 - SpecularStrength(specColor);
#if !UNITY_CONSERVE_ENERGY
return albedo;
#elif UNITY_CONSERVE_ENERGY_MONOCHROME
return albedo * oneMinusReflectivity;
#else
return albedo * (half3(1,1,1) - specColor);
#endif
}
half SpecularStrength(half3 specular)
{
#if (SHADER_TARGET < 30)
// SM2.0: instruction count limitation
// SM2.0: simplified SpecularStrength
return specular.r; // Red channel - because most metals are either monocrhome or with redish/yellowish tint
#else
return max (max (specular.r, specular.g), specular.b);
#endif
}
LobeEnergy???
LobeEnergy[0] : For ClearCloat specular D
LobeEnergy[1] : For specular D
LobeEnergy[2] : (Mainly) Used for diffuse
// DiffuseIBL(), IntegrateBRDF() in PostProcessAmbient.usf
DiffuseIblShading *= ( 1 - 0.3333 * Roughness );