Skip to content

Commit

Permalink
Add blackbody PBR node implementations (#1367)
Browse files Browse the repository at this point in the history
Address the missing targets for the PBR blackbody node implementation
using the following approximation: Wikipedia: Planckian Locus Approximation
Add a simple unlit surface material example using the above blackbody node for emission.
Reenable blackbody node tests.
  • Loading branch information
nicolassavva-autodesk authored Jul 12, 2023
1 parent 2c0c7ea commit 3e838e2
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 6 deletions.
48 changes: 48 additions & 0 deletions libraries/pbrlib/genglsl/mx_blackbody.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/// XYZ to Rec.709 RGB colorspace conversion
const mat3 XYZ_to_RGB = mat3( 3.2406, -0.9689, 0.0557,
-1.5372, 1.8758, -0.2040,
-0.4986, 0.0415, 1.0570);

void mx_blackbody(float temperatureKelvin, out vec3 colorValue)
{
float xc, yc;
float t, t2, t3, xc2, xc3;

// if value outside valid range of approximation clamp to accepted temperature range
temperatureKelvin = clamp(temperatureKelvin, 1667.0, 25000.0);

t = 1000.0 / temperatureKelvin;
t2 = t * t;
t3 = t * t * t;

// Cubic spline approximation for Kelvin temperature to sRGB conversion
// (https://en.wikipedia.org/wiki/Planckian_locus#Approximation)
if (temperatureKelvin < 4000.0) { // 1667K <= temperatureKelvin < 4000K
xc = -0.2661239 * t3 - 0.2343580 * t2 + 0.8776956 * t + 0.179910;
}
else { // 4000K <= temperatureKelvin <= 25000K
xc = -3.0258469 * t3 + 2.1070379 * t2 + 0.2226347 * t + 0.240390;
}
xc2 = xc * xc;
xc3 = xc * xc * xc;

if (temperatureKelvin < 2222.0) { // 1667K <= temperatureKelvin < 2222K
yc = -1.1063814 * xc3 - 1.34811020 * xc2 + 2.18555832 * xc - 0.20219683;
}
else if (temperatureKelvin < 4000.0) { // 2222K <= temperatureKelvin < 4000K
yc = -0.9549476 * xc3 - 1.37418593 * xc2 + 2.09137015 * xc - 0.16748867;
}
else { // 4000K <= temperatureKelvin <= 25000K
yc = 3.0817580 * xc3 - 5.87338670 * xc2 + 3.75112997 * xc - 0.37001483;
}

if (yc <= 0.0) { // avoid division by zero
colorValue = vec3(1.0);
return;
}

vec3 XYZ = vec3(xc / yc, 1.0, (1.0 - xc - yc) / yc);

colorValue = XYZ_to_RGB * XYZ;
colorValue = max(colorValue, vec3(0.0));
}
3 changes: 3 additions & 0 deletions libraries/pbrlib/genglsl/pbrlib_genglsl_impl.mtlx
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,7 @@
<!-- <artistic_ior> -->
<implementation name="IM_artistic_ior_genglsl" nodedef="ND_artistic_ior" file="mx_artistic_ior.glsl" function="mx_artistic_ior" target="genglsl" />

<!-- <blackbody> -->
<implementation name="IM_blackbody_genglsl" nodedef="ND_blackbody" file="mx_blackbody.glsl" function="mx_blackbody" target="genglsl" />

</materialx>
3 changes: 3 additions & 0 deletions libraries/pbrlib/genmsl/pbrlib_genmsl_impl.mtlx
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,7 @@
<!-- <artistic_ior> -->
<implementation name="IM_artistic_ior_genmsl" nodedef="ND_artistic_ior" file="../genglsl/mx_artistic_ior.glsl" function="mx_artistic_ior" target="genmsl" />

<!-- <blackbody> -->
<implementation name="IM_blackbody_genmsl" nodedef="ND_blackbody" file="../genglsl/mx_blackbody.glsl" function="mx_blackbody" target="genmsl" />

</materialx>
48 changes: 48 additions & 0 deletions libraries/pbrlib/genosl/mx_blackbody.osl
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
void mx_blackbody(float temperature, output color color_value)
{
float xc, yc;
float t, t2, t3, xc2, xc3;

// if value outside valid range of approximation clamp to accepted temperature range
temperature = clamp(temperature, 1667.0, 25000.0);

t = 1000.0 / temperature;
t2 = t * t;
t3 = t * t * t;

// Cubic spline approximation for Kelvin temperature to sRGB conversion
// (https://en.wikipedia.org/wiki/Planckian_locus#Approximation)
if (temperature < 4000.0) { // 1667K <= temperature < 4000K
xc = -0.2661239 * t3 - 0.2343580 * t2 + 0.8776956 * t + 0.179910;
}
else { // 4000K <= temperature <= 25000K
xc = -3.0258469 * t3 + 2.1070379 * t2 + 0.2226347 * t + 0.240390;
}
xc2 = xc * xc;
xc3 = xc * xc * xc;

if (temperature < 2222.0) { // 1667K <= temperature < 2222K
yc = -1.1063814 * xc3 - 1.34811020 * xc2 + 2.18555832 * xc - 0.20219683;
}
else if (temperature < 4000.0) { // 2222K <= temperature < 4000K
yc = -0.9549476 * xc3 - 1.37418593 * xc2 + 2.09137015 * xc - 0.16748867;
}
else { // 4000K <= temperature <= 25000K
yc = 3.0817580 * xc3 - 5.87338670 * xc2 + 3.75112997 * xc - 0.37001483;
}

if (yc <= 0.0) { // avoid division by zero
color_value = color(1.0);
return;
}

vector XYZ = vector(xc / yc, 1.0, (1 - xc - yc) / yc);

/// XYZ to Rec.709 RGB colorspace conversion
matrix XYZ_to_RGB = matrix( 3.2406, -0.9689, 0.0557,
-1.5372, 1.8758, -0.2040,
-0.4986, 0.0415, 1.0570);

color_value = transform(XYZ_to_RGB, XYZ);
color_value = max(color_value, vector(0.0));
}
3 changes: 3 additions & 0 deletions libraries/pbrlib/genosl/pbrlib_genosl_impl.legacy
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,7 @@
<!-- <artistic_ior> -->
<implementation name="IM_artistic_ior_genosl" nodedef="ND_artistic_ior" file="mx_artistic_ior.osl" function="mx_artistic_ior" target="genosl" />

<!-- <blackbody> -->
<implementation name="IM_blackbody_genosl" nodedef="ND_blackbody" file="mx_blackbody.osl" function="mx_blackbody" target="genosl" />

</materialx>
3 changes: 3 additions & 0 deletions libraries/pbrlib/genosl/pbrlib_genosl_impl.mtlx
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,7 @@
<!-- <artistic_ior> -->
<implementation name="IM_artistic_ior_genosl" nodedef="ND_artistic_ior" file="mx_artistic_ior.osl" function="mx_artistic_ior" target="genosl" />

<!-- <blackbody> -->
<implementation name="IM_blackbody_genosl" nodedef="ND_blackbody" file="mx_blackbody.osl" function="mx_blackbody" target="genosl" />

</materialx>
16 changes: 16 additions & 0 deletions resources/Materials/TestSuite/pbrlib/bsdf/blackbody.mtlx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<materialx version="1.38" colorspace="lin_rec709">
<nodegraph name="NG_blackbody">
<input name="blackbody_temperature" type="float" value="5000.0" uimin="1500.0" uimax="25000.0" uistep="100.0" uiname="Blackbody Temperature Kelvin" />
<blackbody name="blackbody_color_out" type="color3">
<input name="temperature" type="float" interfacename="blackbody_temperature" />
</blackbody>
<output name="emission_color_output" type="color3" nodename="blackbody_color_out" />
</nodegraph>
<surface_unlit name="SR_blackbody" type="surfaceshader">
<input name="emission_color" type="color3" nodegraph="NG_blackbody" output="emission_color_output" />
</surface_unlit>
<surfacematerial name="Blackbody" type="material">
<input name="surfaceshader" type="surfaceshader" nodename="SR_blackbody" />
</surfacematerial>
</materialx>
2 changes: 1 addition & 1 deletion source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ TEST_CASE("GenShader: GLSL Implementation Check", "[genglsl]")

mx::StringSet generatorSkipNodeTypes;
mx::StringSet generatorSkipNodeDefs;
GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 48);
GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 47);
}

TEST_CASE("GenShader: GLSL Unique Names", "[genglsl]")
Expand Down
2 changes: 1 addition & 1 deletion source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ TEST_CASE("GenShader: MDL Implementation Check", "[genmdl]")
generatorSkipNodeTypes.insert("light");
mx::StringSet generatorSkipNodeDefs;

GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 49);
GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 48);
}


Expand Down
2 changes: 1 addition & 1 deletion source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ TEST_CASE("GenShader: MSL Implementation Check", "[genmsl]")

mx::StringSet generatorSkipNodeTypes;
mx::StringSet generatorSkipNodeDefs;
GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 48);
GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 47);
}

TEST_CASE("GenShader: MSL Unique Names", "[genmsl]")
Expand Down
2 changes: 1 addition & 1 deletion source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ TEST_CASE("GenShader: OSL Implementation Check", "[genosl]")
generatorSkipNodeTypes.insert("light");
mx::StringSet generatorSkipNodeDefs;

GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 49);
GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 48);
}

TEST_CASE("GenShader: OSL Unique Names", "[genosl]")
Expand Down
1 change: 0 additions & 1 deletion source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ void checkImplementations(mx::GenContext& context,
"arrayappend",
"displacement",
"volume",
"blackbody",
"curveadjust",
"conical_edf",
"measured_edf",
Expand Down
2 changes: 1 addition & 1 deletion source/MaterialXView/Editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,7 @@ ng::FloatBox<float>* createFloatWidget(ng::Widget* parent, const std::string& la

if (ui)
{
std::pair<float, float> range(0.0f, 0.0f);
std::pair<float, float> range(0.0f, 1.0f);
if (ui->uiMin)
{
box->set_min_value(ui->uiMin->asA<float>());
Expand Down

0 comments on commit 3e838e2

Please sign in to comment.