diff options
-rw-r--r-- | intern/cycles/kernel/svm/blackbody.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/closure.h | 3 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/math_util.h | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/types.h | 7 | ||||
-rw-r--r-- | intern/cycles/kernel/util/color.h | 9 | ||||
-rw-r--r-- | intern/cycles/scene/shader.cpp | 39 | ||||
-rw-r--r-- | intern/cycles/scene/shader.h | 5 | ||||
-rw-r--r-- | intern/cycles/scene/shader_nodes.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/util/transform.h | 15 |
9 files changed, 78 insertions, 10 deletions
diff --git a/intern/cycles/kernel/svm/blackbody.h b/intern/cycles/kernel/svm/blackbody.h index 1618341b655..af59c2fe747 100644 --- a/intern/cycles/kernel/svm/blackbody.h +++ b/intern/cycles/kernel/svm/blackbody.h @@ -23,7 +23,7 @@ ccl_device_noinline void svm_node_blackbody(KernelGlobals kg, /* Input */ float temperature = stack_load_float(stack, temperature_offset); - float3 color_rgb = svm_math_blackbody_color(temperature); + float3 color_rgb = rec709_to_rgb(kg, svm_math_blackbody_color_rec709(temperature)); stack_store_float3(stack, col_offset, color_rgb); } diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h index 88b44cdbacf..305bd404d27 100644 --- a/intern/cycles/kernel/svm/closure.h +++ b/intern/cycles/kernel/svm/closure.h @@ -1111,7 +1111,8 @@ ccl_device_noinline int svm_node_principled_volume(KernelGlobals kg, if (intensity > CLOSURE_WEIGHT_CUTOFF) { float3 blackbody_tint = stack_load_float3(stack, node.w); - float3 bb = blackbody_tint * intensity * svm_math_blackbody_color(T); + float3 bb = blackbody_tint * intensity * + rec709_to_rgb(kg, svm_math_blackbody_color_rec709(T)); emission_setup(sd, bb); } } diff --git a/intern/cycles/kernel/svm/math_util.h b/intern/cycles/kernel/svm/math_util.h index 2a496aee1e1..9f2d9561e26 100644 --- a/intern/cycles/kernel/svm/math_util.h +++ b/intern/cycles/kernel/svm/math_util.h @@ -189,10 +189,8 @@ ccl_device float svm_math(NodeMathType type, float a, float b, float c) } } -ccl_device float3 svm_math_blackbody_color(float t) +ccl_device float3 svm_math_blackbody_color_rec709(float t) { - /* TODO(lukas): Reimplement in XYZ. */ - /* 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), diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h index db499a1e1bc..422285cd346 100644 --- a/intern/cycles/kernel/types.h +++ b/intern/cycles/kernel/types.h @@ -1117,13 +1117,18 @@ typedef struct KernelFilm { float4 xyz_to_g; float4 xyz_to_b; float4 rgb_to_y; + /* Rec709 to rendering color space. */ + float4 rec709_to_r; + float4 rec709_to_g; + float4 rec709_to_b; + int is_rec709; int pass_bake_primitive; int pass_bake_differential; int use_approximate_shadow_catcher; - int pad1, pad2; + int pad1; } KernelFilm; static_assert_align(KernelFilm, 16); diff --git a/intern/cycles/kernel/util/color.h b/intern/cycles/kernel/util/color.h index 95b6b33795d..28978d873d6 100644 --- a/intern/cycles/kernel/util/color.h +++ b/intern/cycles/kernel/util/color.h @@ -14,6 +14,15 @@ ccl_device float3 xyz_to_rgb(KernelGlobals kg, float3 xyz) dot(float4_to_float3(kernel_data.film.xyz_to_b), xyz)); } +ccl_device float3 rec709_to_rgb(KernelGlobals kg, float3 rec709) +{ + return (kernel_data.film.is_rec709) ? + rec709 : + make_float3(dot(float4_to_float3(kernel_data.film.rec709_to_r), rec709), + dot(float4_to_float3(kernel_data.film.rec709_to_g), rec709), + dot(float4_to_float3(kernel_data.film.rec709_to_b), rec709)); +} + ccl_device float linear_rgb_to_gray(KernelGlobals kg, float3 c) { return dot(c, float4_to_float3(kernel_data.film.rgb_to_y)); diff --git a/intern/cycles/scene/shader.cpp b/intern/cycles/scene/shader.cpp index 8a08f2a5be9..e1af92ea8cf 100644 --- a/intern/cycles/scene/shader.cpp +++ b/intern/cycles/scene/shader.cpp @@ -579,6 +579,10 @@ void ShaderManager::device_update_common(Device * /*device*/, kfilm->xyz_to_g = float3_to_float4(xyz_to_g); kfilm->xyz_to_b = float3_to_float4(xyz_to_b); kfilm->rgb_to_y = float3_to_float4(rgb_to_y); + kfilm->rec709_to_r = float3_to_float4(rec709_to_r); + kfilm->rec709_to_g = float3_to_float4(rec709_to_g); + kfilm->rec709_to_b = float3_to_float4(rec709_to_b); + kfilm->is_rec709 = is_rec709; } void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene) @@ -740,6 +744,11 @@ float ShaderManager::linear_rgb_to_gray(float3 c) return dot(c, rgb_to_y); } +float3 ShaderManager::rec709_to_scene_linear(float3 c) +{ + return make_float3(dot(rec709_to_r, c), dot(rec709_to_g, c), dot(rec709_to_b, c)); +} + string ShaderManager::get_cryptomatte_materials(Scene *scene) { string manifest = "{"; @@ -802,11 +811,29 @@ void ShaderManager::init_xyz_transforms() { /* Default to ITU-BT.709 in case no appropriate transform found. * Note XYZ here is defined as having a D65 white point. */ - xyz_to_r = make_float3(3.2404542f, -1.5371385f, -0.4985314f); - xyz_to_g = make_float3(-0.9692660f, 1.8760108f, 0.0415560f); - xyz_to_b = make_float3(0.0556434f, -0.2040259f, 1.0572252f); + const Transform xyz_to_rec709 = make_transform(3.2404542f, + -1.5371385f, + -0.4985314f, + 0.0f, + -0.9692660f, + 1.8760108f, + 0.0415560f, + 0.0f, + 0.0556434f, + -0.2040259f, + 1.0572252f, + 0.0f); + + xyz_to_r = float4_to_float3(xyz_to_rec709.x); + xyz_to_g = float4_to_float3(xyz_to_rec709.y); + xyz_to_b = float4_to_float3(xyz_to_rec709.z); rgb_to_y = make_float3(0.2126729f, 0.7151522f, 0.0721750f); + rec709_to_r = make_float3(1.0f, 0.0f, 0.0f); + rec709_to_g = make_float3(0.0f, 1.0f, 0.0f); + rec709_to_b = make_float3(0.0f, 0.0f, 1.0f); + is_rec709 = true; + #ifdef WITH_OCIO /* Get from OpenColorO config if it has the required roles. */ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig(); @@ -857,6 +884,12 @@ void ShaderManager::init_xyz_transforms() const Transform rgb_to_xyz = transform_inverse(xyz_to_rgb); rgb_to_y = float4_to_float3(rgb_to_xyz.y); + + const Transform rec709_to_rgb = xyz_to_rgb * transform_inverse(xyz_to_rec709); + rec709_to_r = float4_to_float3(rec709_to_rgb.x); + rec709_to_g = float4_to_float3(rec709_to_rgb.y); + rec709_to_b = float4_to_float3(rec709_to_rgb.z); + is_rec709 = transform_equal_threshold(xyz_to_rgb, xyz_to_rec709, 0.0001f); #endif } diff --git a/intern/cycles/scene/shader.h b/intern/cycles/scene/shader.h index cbe331d8ec2..274bb9b4fa1 100644 --- a/intern/cycles/scene/shader.h +++ b/intern/cycles/scene/shader.h @@ -208,6 +208,7 @@ class ShaderManager { static void free_memory(); float linear_rgb_to_gray(float3 c); + float3 rec709_to_scene_linear(float3 c); string get_cryptomatte_materials(Scene *scene); @@ -239,6 +240,10 @@ class ShaderManager { float3 xyz_to_g; float3 xyz_to_b; float3 rgb_to_y; + float3 rec709_to_r; + float3 rec709_to_g; + float3 rec709_to_b; + bool is_rec709; }; CCL_NAMESPACE_END diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index a951a558731..95fccf725f3 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -5763,7 +5763,9 @@ BlackbodyNode::BlackbodyNode() : ShaderNode(get_node_type()) void BlackbodyNode::constant_fold(const ConstantFolder &folder) { if (folder.all_inputs_constant()) { - folder.make_constant(svm_math_blackbody_color(temperature)); + 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); } } diff --git a/intern/cycles/util/transform.h b/intern/cycles/util/transform.h index 371dbb0f4aa..477272f0ba6 100644 --- a/intern/cycles/util/transform.h +++ b/intern/cycles/util/transform.h @@ -285,6 +285,21 @@ ccl_device_inline bool operator!=(const Transform &A, const Transform &B) return !(A == B); } +ccl_device_inline bool transform_equal_threshold(const Transform &A, + const Transform &B, + const float threshold) +{ + for (int x = 0; x < 3; x++) { + for (int y = 0; y < 4; y++) { + if (fabsf(A[x][y] - B[x][y]) > threshold) { + return false; + } + } + } + + return true; +} + ccl_device_inline float3 transform_get_column(const Transform *t, int column) { return make_float3(t->x[column], t->y[column], t->z[column]); |