[Bf-blender-cvs] [a22ad7fbd39] blender-v3.2-release: Fix T98036: Cycles blackbody inaccurate for low temperature and wide gamut

Brecht Van Lommel noreply at git.blender.org
Mon May 23 22:22:50 CEST 2022


Commit: a22ad7fbd391acc65b99336eae0df5c2a49553d9
Author: Brecht Van Lommel
Date:   Mon May 23 20:27:13 2022 +0200
Branches: blender-v3.2-release
https://developer.blender.org/rBa22ad7fbd391acc65b99336eae0df5c2a49553d9

Fix T98036: Cycles blackbody inaccurate for low temperature and wide gamut

Regenerate blackbody RGB curve fit to not clamp values, and extend down to
800K since it does now change below 965K.

Note that as before, blackbody is only defined in the range 800K to 12000K
and has a fixed value outside of that. But within that range there should
be no more unnecessary gamut clamping.

===================================================================

M	intern/cycles/kernel/svm/blackbody.h
M	intern/cycles/kernel/svm/math_util.h
M	intern/cycles/kernel/tables.h
M	intern/cycles/scene/shader_nodes.cpp
M	intern/cycles/test/render_graph_finalize_test.cpp

===================================================================

diff --git a/intern/cycles/kernel/svm/blackbody.h b/intern/cycles/kernel/svm/blackbody.h
index af59c2fe747..774fa16b384 100644
--- a/intern/cycles/kernel/svm/blackbody.h
+++ b/intern/cycles/kernel/svm/blackbody.h
@@ -24,6 +24,7 @@ ccl_device_noinline void svm_node_blackbody(KernelGlobals kg,
   float temperature = stack_load_float(stack, temperature_offset);
 
   float3 color_rgb = rec709_to_rgb(kg, svm_math_blackbody_color_rec709(temperature));
+  color_rgb = max(color_rgb, zero_float3());
 
   stack_store_float3(stack, col_offset, color_rgb);
 }
diff --git a/intern/cycles/kernel/svm/math_util.h b/intern/cycles/kernel/svm/math_util.h
index 9f2d9561e26..89bd4a501a7 100644
--- a/intern/cycles/kernel/svm/math_util.h
+++ b/intern/cycles/kernel/svm/math_util.h
@@ -192,28 +192,26 @@ ccl_device float svm_math(NodeMathType type, float a, float b, float c)
 ccl_device float3 svm_math_blackbody_color_rec709(float t)
 {
   /* Calculate color in range 800..12000 using an approximation
-   * a/x+bx+c for R and G and ((at + b)t + c)t + d) for B
-   * Max absolute error for RGB is (0.00095, 0.00077, 0.00057),
-   * which is enough to get the same 8 bit/channel color.
-   */
+   * a/x+bx+c for R and G and ((at + b)t + c)t + d) for B.
+   *
+   * The result of this can be negative to support gamut wider than
+   * than rec.709, just needs to be clamped. */
 
   if (t >= 12000.0f) {
-    return make_float3(0.826270103f, 0.994478524f, 1.56626022f);
+    return make_float3(0.8262954810464208f, 0.9945080501520986f, 1.566307710274283f);
   }
-  else if (t < 965.0f) {
-    /* For 800 <= t < 965 color does not change in OSL implementation, so keep color the same */
-    return make_float3(4.70366907f, 0.0f, 0.0f);
+  else if (t < 800.0f) {
+    /* Arbitrary lower limit where light is very dim, matching OSL. */
+    return make_float3(5.413294490189271f, -0.20319390035873933f, -0.0822535242887164f);
   }
 
-  /* Manually align for readability. */
-  /* clang-format off */
-  int i = (t >= 6365.0f) ? 5 :
-          (t >= 3315.0f) ? 4 :
-          (t >= 1902.0f) ? 3 :
-          (t >= 1449.0f) ? 2 :
-          (t >= 1167.0f) ? 1 :
+  int i = (t >= 6365.0f) ? 6 :
+          (t >= 3315.0f) ? 5 :
+          (t >= 1902.0f) ? 4 :
+          (t >= 1449.0f) ? 3 :
+          (t >= 1167.0f) ? 2 :
+          (t >= 965.0f)  ? 1 :
                            0;
-  /* clang-format on */
 
   ccl_constant float *r = blackbody_table_r[i];
   ccl_constant float *g = blackbody_table_g[i];
diff --git a/intern/cycles/kernel/tables.h b/intern/cycles/kernel/tables.h
index f826cc5c5ef..c1fdbba3fa7 100644
--- a/intern/cycles/kernel/tables.h
+++ b/intern/cycles/kernel/tables.h
@@ -4,30 +4,33 @@
 /* clang-format off */
 
 ccl_inline_constant float blackbody_table_r[][3] = {
-  {2.52432244e+03f, -1.06185848e-03f, 3.11067539e+00f},
-  {3.37763626e+03f, -4.34581697e-04f, 1.64843306e+00f},
-  {4.10671449e+03f, -8.61949938e-05f, 6.41423749e-01f},
-  {4.66849800e+03f, 2.85655028e-05f, 1.29075375e-01f},
-  {4.60124770e+03f, 2.89727618e-05f, 1.48001316e-01f},
-  {3.78765709e+03f, 9.36026367e-06f, 3.98995841e-01f}
+ {1.61919106e+03f, -2.05010916e-03f, 5.02995757e+00f},
+ {2.48845471e+03f, -1.11330907e-03f, 3.22621544e+00f},
+ {3.34143193e+03f, -4.86551192e-04f, 1.76486769e+00f},
+ {4.09461742e+03f, -1.27446582e-04f, 7.25731635e-01f},
+ {4.67028036e+03f, 2.91258199e-05f, 1.26703442e-01f},
+ {4.59509185e+03f, 2.87495649e-05f, 1.50345020e-01f},
+ {3.78717450e+03f, 9.35907826e-06f, 3.99075871e-01f}
 };
 
 ccl_inline_constant float blackbody_table_g[][3] = {
-  {-7.50343014e+02f, 3.15679613e-04f, 4.73464526e-01f},
-  {-1.00402363e+03f, 1.29189794e-04f, 9.08181524e-01f},
-  {-1.22075471e+03f, 2.56245413e-05f, 1.20753416e+00f},
-  {-1.42546105e+03f, -4.01730887e-05f, 1.44002695e+00f},
-  {-1.18134453e+03f, -2.18913373e-05f, 1.30656109e+00f},
-  {-5.00279505e+02f, -4.59745390e-06f, 1.09090465e+00f}
+ {-4.88999748e+02f, 6.04330754e-04f, -7.55807526e-02f},
+ {-7.55994277e+02f, 3.16730098e-04f, 4.78306139e-01f},
+ {-1.02363977e+03f, 1.20223470e-04f, 9.36662319e-01f},
+ {-1.26571316e+03f, 4.87340896e-06f, 1.27054498e+00f},
+ {-1.42529332e+03f, -4.01150431e-05f, 1.43972784e+00f},
+ {-1.17554822e+03f, -2.16378048e-05f, 1.30408023e+00f},
+ {-5.00799571e+02f, -4.59832026e-06f, 1.09098763e+00f}
 };
 
 ccl_inline_constant float blackbody_table_b[][4] = {
-  {0.0f, 0.0f, 0.0f, 0.0f}, /* zeros should be optimized by compiler */
-  {0.0f, 0.0f, 0.0f, 0.0f},
-  {0.0f, 0.0f, 0.0f, 0.0f},
-  {-2.02524603e-11f, 1.79435860e-07f, -2.60561875e-04f, -1.41761141e-02f},
-  {-2.22463426e-13f, -1.55078698e-08f, 3.81675160e-04f, -7.30646033e-01f},
-  {6.72595954e-13f, -2.73059993e-08f, 4.24068546e-04f, -7.52204323e-01f}
+ {5.96945309e-11f, -4.85742887e-08f, -9.70622247e-05f, -4.07936148e-03f},
+ {2.40430366e-11f, 5.55021075e-08f, -1.98503712e-04f, 2.89312858e-02f},
+ {-1.40949732e-11f, 1.89878968e-07f, -3.56632824e-04f, 9.10767778e-02f},
+ {-3.61460868e-11f, 2.84822009e-07f, -4.93211319e-04f, 1.56723440e-01f},
+ {-1.97075738e-11f, 1.75359352e-07f, -2.50542825e-04f, -2.22783266e-02f},
+ {-1.61997957e-13f, -1.64216008e-08f, 3.86216271e-04f, -7.38077418e-01f},
+ {6.72650283e-13f, -2.73078809e-08f, 4.24098264e-04f, -7.52335691e-01f}
 };
 
 ccl_inline_constant float cie_colour_match[][3] = {
diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp
index 95fccf725f3..dce92dbe4da 100644
--- a/intern/cycles/scene/shader_nodes.cpp
+++ b/intern/cycles/scene/shader_nodes.cpp
@@ -5765,7 +5765,7 @@ void BlackbodyNode::constant_fold(const ConstantFolder &folder)
   if (folder.all_inputs_constant()) {
     const float3 rgb_rec709 = svm_math_blackbody_color_rec709(temperature);
     const float3 rgb = folder.scene->shader_manager->rec709_to_scene_linear(rgb_rec709);
-    folder.make_constant(rgb);
+    folder.make_constant(max(rgb, zero_float3()));
   }
 }
 
diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp
index 143628f1e30..dac36ab0135 100644
--- a/intern/cycles/test/render_graph_finalize_test.cpp
+++ b/intern/cycles/test/render_graph_finalize_test.cpp
@@ -946,7 +946,7 @@ TEST_F(RenderGraph, constant_fold_bright_contrast)
 TEST_F(RenderGraph, constant_fold_blackbody)
 {
   EXPECT_ANY_MESSAGE(log);
-  CORRECT_INFO_MESSAGE(log, "Folding Blackbody::Color to constant (3.94163, 0.226523, 0).");
+  CORRECT_INFO_MESSAGE(log, "Folding Blackbody::Color to constant (3.96553, 0.227897, 0).");
 
   builder
       .add_node(ShaderNodeBuilder<BlackbodyNode>(graph, "Blackbody").set("Temperature", 1200.0f))



More information about the Bf-blender-cvs mailing list