Cheap Energy Conversations for game PBS

この記事について

  • ゲーム向けの 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;

Substance Player (v5.3.3)

// 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
}

Unreal Engine 4.12

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