From d35221e2613f2341ed9a1a382a2cda05a7ed85cd Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Mon, 28 Dec 2015 02:59:54 +0100 Subject: [PATCH 2/4] Cycles: Provide color space conversion matrices for the kernel --- intern/cycles/blender/blender_sync.cpp | 15 +++++++++++++++ intern/cycles/kernel/kernel_film.h | 32 ++++++++++++++++++++++++++++++++ intern/cycles/kernel/kernel_types.h | 6 ++++++ intern/cycles/render/film.cpp | 16 +++++++++++++++- intern/cycles/render/film.h | 9 +++++++++ intern/cycles/util/util_math.h | 20 ++++++++++++++++++++ 6 files changed, 97 insertions(+), 1 deletion(-) diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 4b2fa61..e263280 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -302,6 +302,21 @@ void BlenderSync::sync_film() } } + float xyz_to_rgb[9], rgb_to_xyz[9]; + b_engine.xyz_to_scene_linear_matrix(xyz_to_rgb); + film->x_to_rgb = make_float3(xyz_to_rgb[0], xyz_to_rgb[1], xyz_to_rgb[2]); + film->y_to_rgb = make_float3(xyz_to_rgb[3], xyz_to_rgb[4], xyz_to_rgb[5]); + film->z_to_rgb = make_float3(xyz_to_rgb[6], xyz_to_rgb[7], xyz_to_rgb[8]); + invert_m3(rgb_to_xyz, xyz_to_rgb); + film->r_to_xyz = make_float3(rgb_to_xyz[0], rgb_to_xyz[1], rgb_to_xyz[2]); + film->g_to_xyz = make_float3(rgb_to_xyz[3], rgb_to_xyz[4], rgb_to_xyz[5]); + film->b_to_xyz = make_float3(rgb_to_xyz[6], rgb_to_xyz[7], rgb_to_xyz[8]); + +#if 0 + printf("XYZ to RGB:\n%f %f %f\n%f %f %f\n%f %f %f\n", (double)xyz_to_rgb[0], (double)xyz_to_rgb[3], (double)xyz_to_rgb[6], (double)xyz_to_rgb[1], (double)xyz_to_rgb[4], (double)xyz_to_rgb[7], (double)xyz_to_rgb[2], (double)xyz_to_rgb[5], (double)xyz_to_rgb[8]); + printf("RGB to XYZ:\n%f %f %f\n%f %f %f\n%f %f %f\n", (double)rgb_to_xyz[0], (double)rgb_to_xyz[3], (double)rgb_to_xyz[6], (double)rgb_to_xyz[1], (double)rgb_to_xyz[4], (double)rgb_to_xyz[7], (double)rgb_to_xyz[2], (double)rgb_to_xyz[5], (double)rgb_to_xyz[8]); +#endif + if(film->modified(prevfilm)) film->tag_update(scene); } diff --git a/intern/cycles/kernel/kernel_film.h b/intern/cycles/kernel/kernel_film.h index f9e9b41..5203ae2 100644 --- a/intern/cycles/kernel/kernel_film.h +++ b/intern/cycles/kernel/kernel_film.h @@ -16,6 +16,38 @@ CCL_NAMESPACE_BEGIN +ccl_device float3 xyz_to_scene_linear(KernelGlobals *kg, float3 xyz) +{ + return xyz.x * kernel_data.film.x_to_rgb + + xyz.y * kernel_data.film.y_to_rgb + + xyz.z * kernel_data.film.z_to_rgb; +} + +ccl_device float3 scene_linear_to_xyz(KernelGlobals *kg, float3 c) +{ + return c.x * kernel_data.film.r_to_xyz + + c.y * kernel_data.film.g_to_xyz + + c.z * kernel_data.film.b_to_xyz; +} + +ccl_device float scene_linear_to_gray(KernelGlobals *kg, float3 c) +{ + return kernel_data.film.r_to_xyz.y * c.x + + kernel_data.film.g_to_xyz.y * c.y + + kernel_data.film.b_to_xyz.y * c.z; +} + +/* TODO(lukas): Is there a better approach? */ +ccl_device float3 hsv_to_scene_linear(KernelGlobals *kg, float3 hsv) +{ + return hsv_to_rec709(hsv); +} + +ccl_device float3 scene_linear_to_hsv(KernelGlobals *kg, float3 c) +{ + return rec709_to_hsv(c); +} + ccl_device float4 film_map(KernelGlobals *kg, float4 irradiance, float scale) { float exposure = kernel_data.film.exposure; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 04d013c..eec2986 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -904,6 +904,12 @@ typedef struct KernelFilm { int pass_ray_bounces; int pass_pad3; #endif + float3 x_to_rgb; + float3 y_to_rgb; + float3 z_to_rgb; + float3 r_to_xyz; + float3 g_to_xyz; + float3 b_to_xyz; } KernelFilm; typedef struct KernelBackground { diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index abdd1c2..e15eb17 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -436,6 +436,14 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) kfilm->mist_inv_depth = (mist_depth > 0.0f)? 1.0f/mist_depth: 0.0f; kfilm->mist_falloff = mist_falloff; + /* color space */ + kfilm->r_to_xyz = r_to_xyz; + kfilm->g_to_xyz = g_to_xyz; + kfilm->b_to_xyz = b_to_xyz; + kfilm->x_to_rgb = x_to_rgb; + kfilm->y_to_rgb = y_to_rgb; + kfilm->z_to_rgb = z_to_rgb; + need_update = false; } @@ -459,7 +467,13 @@ bool Film::modified(const Film& film) && filter_width == film.filter_width && mist_start == film.mist_start && mist_depth == film.mist_depth - && mist_falloff == film.mist_falloff); + && mist_falloff == film.mist_falloff + && r_to_xyz == film.r_to_xyz + && g_to_xyz == film.g_to_xyz + && b_to_xyz == film.b_to_xyz + && x_to_rgb == film.x_to_rgb + && y_to_rgb == film.y_to_rgb + && z_to_rgb == film.z_to_rgb); } void Film::tag_passes_update(Scene *scene, const vector& passes_) diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h index 0fde928..38464e9 100644 --- a/intern/cycles/render/film.h +++ b/intern/cycles/render/film.h @@ -57,6 +57,15 @@ public: float filter_width; size_t filter_table_offset; + /* Color space conversion between the scene linear space and CIE XYZ + * In this context, xyz are the three components of XYZ space, while rgb are the components of the scene linear space. + * This is pure notation, for example, XYZ could also be used as the scene linear space, in which case the two would be identical. + * The float3's below always express one primary of the source space in the target space, so e.g. converting RGB->XYZ is done by: + * float3 xyz = R * r_to_xyz + G * g_to_xyz + B * b_to_xyz; + */ + float3 x_to_rgb, y_to_rgb, z_to_rgb; + float3 r_to_xyz, g_to_xyz, b_to_xyz; + float mist_start; float mist_depth; float mist_falloff; diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 4a676d0..72e0cbd 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -1514,6 +1514,26 @@ ccl_device_inline int util_max_axis(float3 vec) } } +ccl_device_inline void invert_m3(float *imat, float *mat) +{ + float det = mat[0]*mat[4]*mat[8] + + mat[1]*mat[5]*mat[6] + + mat[2]*mat[3]*mat[7] + - mat[6]*mat[4]*mat[2] + - mat[7]*mat[5]*mat[0] + - mat[8]*mat[3]*mat[1]; + float idet = 1.0f / det; + imat[0] = (mat[4]*mat[8] - mat[5]*mat[7]) * idet; + imat[1] = (mat[2]*mat[7] - mat[1]*mat[8]) * idet; + imat[2] = (mat[1]*mat[5] - mat[2]*mat[4]) * idet; + imat[3] = (mat[5]*mat[6] - mat[3]*mat[8]) * idet; + imat[4] = (mat[0]*mat[8] - mat[2]*mat[6]) * idet; + imat[5] = (mat[2]*mat[3] - mat[0]*mat[5]) * idet; + imat[6] = (mat[3]*mat[7] - mat[4]*mat[6]) * idet; + imat[7] = (mat[1]*mat[6] - mat[0]*mat[7]) * idet; + imat[8] = (mat[0]*mat[4] - mat[1]*mat[3]) * idet; +} + CCL_NAMESPACE_END #endif /* __UTIL_MATH_H__ */ -- 1.9.1