From 805d6fcb803d9fc55a066dff5af46b117d39a348 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sun, 1 May 2016 22:20:31 +0200 Subject: [PATCH 3/4] Cycles: Use proper XYZ <-> Scene Linear conversion instead of assuming sRGB There are multiple places in Cycles where values were specified in XYZ since they're coming from physical models. Currently, a fixed XYZ <-> Linear sRGB transform is used, which is wrong as soon as a different scene linear color space is used. In this commit, the new Render API functions are used to get a correct transform, which is then used instead of the fixed one. Another calculation that depends on the Scene Linear space is Luminance, so this now uses the correct conversion as well. --- intern/cycles/blender/blender_curves.cpp | 15 ++++--- intern/cycles/blender/blender_mesh.cpp | 9 ++-- intern/cycles/blender/blender_sync.cpp | 8 ++++ intern/cycles/kernel/CMakeLists.txt | 1 + intern/cycles/kernel/kernel_film.h | 18 ++++---- intern/cycles/kernel/kernel_types.h | 6 +++ intern/cycles/kernel/svm/svm.h | 4 +- intern/cycles/kernel/svm/svm_blackbody.h | 5 ++- intern/cycles/kernel/svm/svm_convert.h | 6 +-- intern/cycles/kernel/svm/svm_math_util.h | 74 +++++++------------------------ intern/cycles/kernel/svm/svm_sky.h | 5 +-- intern/cycles/kernel/svm/svm_wavelength.h | 8 ++-- intern/cycles/render/film.cpp | 8 ++++ intern/cycles/render/film.h | 9 ++++ intern/cycles/render/nodes.cpp | 5 ++- intern/cycles/util/util_color.h | 48 ++++++++++++-------- intern/cycles/util/util_math.h | 20 +++++++++ 17 files changed, 138 insertions(+), 111 deletions(-) diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 0178bfb..42326cd 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -764,17 +764,18 @@ void ExportCurveTriangleVcol(ParticleCurveData *CData, int vert_offset, int reso for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) { for(int section = 0; section < resol; section++) { - cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); + /* Assume vertex colors are in sRGB color space, these aren't used for color-critical operations anyways. */ + cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear(CData->curve_vcol[curve])); vertexindex++; - cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear(CData->curve_vcol[curve])); vertexindex++; - cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear(CData->curve_vcol[curve])); vertexindex++; - cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear(CData->curve_vcol[curve])); vertexindex++; - cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear(CData->curve_vcol[curve])); vertexindex++; - cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear(CData->curve_vcol[curve])); vertexindex++; } } @@ -991,7 +992,7 @@ void BlenderSync::sync_curves(Mesh *mesh, for(size_t curve = 0; curve < CData.curve_vcol.size(); curve++) if(!(CData.curve_keynum[curve] <= 1 || CData.curve_length[curve] == 0.0f)) - fdata[i++] = color_srgb_to_scene_linear(CData.curve_vcol[curve]); + fdata[i++] = color_srgb_to_linear(CData.curve_vcol[curve]); } } } diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 55ef913..3fc0a91 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -353,12 +353,13 @@ static void attr_create_vertex_color(Scene *scene, int tri_a[3], tri_b[3]; face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b); + /* Assume vertex colors are in sRGB color space, these aren't used for color-critical operations anyways. */ uchar4 colors[4]; - colors[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1()))); - colors[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2()))); - colors[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3()))); + colors[0] = color_float_to_byte(color_srgb_to_linear(get_float3(c->color1()))); + colors[1] = color_float_to_byte(color_srgb_to_linear(get_float3(c->color2()))); + colors[2] = color_float_to_byte(color_srgb_to_linear(get_float3(c->color3()))); if(nverts[i] == 4) { - colors[3] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4()))); + colors[3] = color_float_to_byte(color_srgb_to_linear(get_float3(c->color4()))); } cdata[0] = colors[tri_a[0]]; diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 6291b38..8ba3f39 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -358,6 +358,14 @@ void BlenderSync::sync_film() } } + float xyz_to_rgb[9], rgb_to_xyz[9]; + b_engine.xyz_to_scene_linear_matrix(xyz_to_rgb); + for(int i = 0; i < 3; i++) + film->xyz_to_rgb[i] = make_float3(xyz_to_rgb[3*i], xyz_to_rgb[3*i+1], xyz_to_rgb[3*i+2]); + invert_m3(rgb_to_xyz, xyz_to_rgb); + for(int i = 0; i < 3; i++) + film->rgb_to_xyz[i] = make_float3(rgb_to_xyz[3*i], rgb_to_xyz[3*i+1], rgb_to_xyz[3*i+2]); + if(film->modified(prevfilm)) film->tag_update(scene); } diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 9f3fb66..d130740 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -32,6 +32,7 @@ set(SRC_HEADERS kernel_accumulate.h kernel_bake.h kernel_camera.h + kernel_color.h kernel_compat_cpu.h kernel_compat_cuda.h kernel_compat_opencl.h diff --git a/intern/cycles/kernel/kernel_film.h b/intern/cycles/kernel/kernel_film.h index f9e9b41..b70de75 100644 --- a/intern/cycles/kernel/kernel_film.h +++ b/intern/cycles/kernel/kernel_film.h @@ -14,22 +14,24 @@ * limitations under the License. */ +#include "kernel_color.h" + CCL_NAMESPACE_BEGIN ccl_device float4 film_map(KernelGlobals *kg, float4 irradiance, float scale) { float exposure = kernel_data.film.exposure; - float4 result = irradiance*scale; + float3 result = make_float3(irradiance.x, irradiance.y, irradiance.z)*scale; + /* TODO(lukas): Instead of converting to sRGB here and drawing with OCIO sRGB->Display, leave in scene linear and draw with OCIO Scene->Display. */ + result = xyz_to_rec709(scene_linear_to_xyz(kg, result)); /* conversion to srgb */ - result.x = color_scene_linear_to_srgb(result.x*exposure); - result.y = color_scene_linear_to_srgb(result.y*exposure); - result.z = color_scene_linear_to_srgb(result.z*exposure); - - /* clamp since alpha might be > 1.0 due to russian roulette */ - result.w = saturate(result.w); + result.x = color_linear_to_srgb(result.x*exposure); + result.y = color_linear_to_srgb(result.y*exposure); + result.z = color_linear_to_srgb(result.z*exposure); - return result; + /* clamp alpha since it might be > 1.0 due to russian roulette */ + return make_float4(result.x, result.y, result.z, saturate(irradiance.w*scale)); } ccl_device uchar4 film_float_to_byte(float4 color) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index c9a895d..a7ba171 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -1018,6 +1018,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/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 9865da2..b8d2a32 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -237,7 +237,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a svm_node_geometry(kg, sd, stack, node.y, node.z); break; case NODE_CONVERT: - svm_node_convert(sd, stack, node.y, node.z, node.w); + svm_node_convert(kg, sd, stack, node.y, node.z, node.w); break; case NODE_TEX_COORD: svm_node_tex_coord(kg, sd, path_flag, stack, node, &offset); @@ -441,7 +441,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a svm_node_wireframe(kg, sd, stack, node); break; case NODE_WAVELENGTH: - svm_node_wavelength(sd, stack, node.y, node.z); + svm_node_wavelength(kg, sd, stack, node.y, node.z); break; case NODE_BLACKBODY: svm_node_blackbody(kg, sd, stack, node.y, node.z); diff --git a/intern/cycles/kernel/svm/svm_blackbody.h b/intern/cycles/kernel/svm/svm_blackbody.h index b750ad8..03900ec 100644 --- a/intern/cycles/kernel/svm/svm_blackbody.h +++ b/intern/cycles/kernel/svm/svm_blackbody.h @@ -39,10 +39,11 @@ ccl_device void svm_node_blackbody(KernelGlobals *kg, ShaderData *sd, float *sta /* Input */ float temperature = stack_load_float(stack, temperature_offset); - float3 color_rgb = svm_math_blackbody_color(temperature); + float3 color = svm_math_blackbody_xyz(temperature); + color = xyz_to_scene_linear(kg, color); if(stack_valid(col_offset)) - stack_store_float3(stack, col_offset, color_rgb); + stack_store_float3(stack, col_offset, color); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_convert.h b/intern/cycles/kernel/svm/svm_convert.h index 3408037..a35128c 100644 --- a/intern/cycles/kernel/svm/svm_convert.h +++ b/intern/cycles/kernel/svm/svm_convert.h @@ -18,7 +18,7 @@ CCL_NAMESPACE_BEGIN /* Conversion Nodes */ -ccl_device void svm_node_convert(ShaderData *sd, float *stack, uint type, uint from, uint to) +ccl_device void svm_node_convert(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint from, uint to) { switch(type) { case NODE_CONVERT_FI: { @@ -33,13 +33,13 @@ ccl_device void svm_node_convert(ShaderData *sd, float *stack, uint type, uint f } case NODE_CONVERT_CF: { float3 f = stack_load_float3(stack, from); - float g = linear_rgb_to_gray(f); + float g = scene_linear_to_gray(kg, f); stack_store_float(stack, to, g); break; } case NODE_CONVERT_CI: { float3 f = stack_load_float3(stack, from); - int i = (int)linear_rgb_to_gray(f); + int i = (int)scene_linear_to_gray(kg, f); stack_store_int(stack, to, i); break; } diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h index 3f7d18a..83e023b 100644 --- a/intern/cycles/kernel/svm/svm_math_util.h +++ b/intern/cycles/kernel/svm/svm_math_util.h @@ -104,66 +104,24 @@ ccl_device float svm_math(NodeMath type, float Fac1, float Fac2) return Fac; } -ccl_device float3 svm_math_blackbody_color(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. - */ - - const float rc[6][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 }, - }; - - const float gc[6][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 }, - }; - - const float bc[6][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 }, - }; - - if(t >= 12000.0f) - return make_float3(0.826270103f, 0.994478524f, 1.56626022f); - - /* Define a macro to reduce stack usage for nvcc */ -#define MAKE_BB_RGB(i) make_float3(\ - rc[i][0] / t + rc[i][1] * t + rc[i][2],\ - gc[i][0] / t + gc[i][1] * t + gc[i][2],\ - ((bc[i][0] * t + bc[i][1]) * t + bc[i][2]) * t + bc[i][3]) - - if(t >= 6365.0f) - return MAKE_BB_RGB(5); - if(t >= 3315.0f) - return MAKE_BB_RGB(4); - if(t >= 1902.0f) - return MAKE_BB_RGB(3); - if(t >= 1449.0f) - return MAKE_BB_RGB(2); - if(t >= 1167.0f) - return MAKE_BB_RGB(1); - if(t >= 965.0f) - return MAKE_BB_RGB(0); +ccl_device float3 svm_math_blackbody_xyz(float t) { + float x_c; + t = clamp(t, 1667.0f, 25000.0f); + float invT = 1000.0f / t; + if(t < 4000.0f) + x_c = ((-0.2661239f * invT - 0.2343580f) * invT + 0.8776956f) * invT + 0.179910f; + else + x_c = ((-3.0258469f * invT + 2.1070379f) * invT + 0.2226347f) * invT + 0.240390f; -#undef MAKE_BB_RGB + float y_c; + if(t < 2222.0f) + y_c = ((-1.1063814f * x_c - 1.34811020f) * x_c + 2.18555832f) * x_c - 0.20219683f; + else if(t < 4000.0f) + y_c = ((-0.9549276f * x_c - 1.37418593f) * x_c + 2.09137015f) * x_c - 0.16748867f; + else + y_c = (( 3.0817580f * x_c - 5.87338760f) * x_c + 3.75112997f) * x_c - 0.37001483f; - /* 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); + return xyY_to_xyz(x_c, y_c, 1.0f); } ccl_device_inline float3 svm_math_gamma_color(float3 color, float gamma) diff --git a/intern/cycles/kernel/svm/svm_sky.h b/intern/cycles/kernel/svm/svm_sky.h index 854e85f..ea43a8c 100644 --- a/intern/cycles/kernel/svm/svm_sky.h +++ b/intern/cycles/kernel/svm/svm_sky.h @@ -58,8 +58,7 @@ ccl_device float3 sky_radiance_old(KernelGlobals *kg, float3 dir, float Y = radiance_x * sky_perez_function(config_x, theta, gamma); /* convert to RGB */ - float3 xyz = xyY_to_xyz(x, y, Y); - return xyz_to_rgb(xyz.x, xyz.y, xyz.z); + return xyz_to_scene_linear(kg, xyY_to_xyz(x, y, Y)); } /* @@ -102,7 +101,7 @@ ccl_device float3 sky_radiance_new(KernelGlobals *kg, float3 dir, float z = sky_radiance_internal(config_z, theta, gamma) * radiance_z; /* convert to RGB and adjust strength */ - return xyz_to_rgb(x, y, z) * (M_2PI_F/683); + return xyz_to_scene_linear(kg, make_float3(x, y, z) * (M_2PI_F/683)); } ccl_device void svm_node_tex_sky(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset) diff --git a/intern/cycles/kernel/svm/svm_wavelength.h b/intern/cycles/kernel/svm/svm_wavelength.h index 57030f39..01a86e9 100644 --- a/intern/cycles/kernel/svm/svm_wavelength.h +++ b/intern/cycles/kernel/svm/svm_wavelength.h @@ -34,7 +34,7 @@ CCL_NAMESPACE_BEGIN /* Wavelength to RGB */ -ccl_device void svm_node_wavelength(ShaderData *sd, float *stack, uint wavelength, uint color_out) +ccl_device void svm_node_wavelength(KernelGlobals *kg, ShaderData *sd, float *stack, uint wavelength, uint color_out) { // CIE colour matching functions xBar, yBar, and zBar for // wavelengths from 380 through 780 nanometers, every 5 @@ -85,9 +85,9 @@ ccl_device void svm_node_wavelength(ShaderData *sd, float *stack, uint wavelengt const float *c = cie_colour_match[i]; color = interp(make_float3(c[0], c[1], c[2]), make_float3(c[3], c[4], c[5]), ii); } - - color = xyz_to_rgb(color.x, color.y, color.z); - color *= 1.0f/2.52f; // Empirical scale from lg to make all comps <= 1 + + color *= 1.0f/2.52f; /* Empirical factor from old code */ + color = xyz_to_scene_linear(kg, color); /* Clamp to zero if values are smaller */ color = max(color, make_float3(0.0f, 0.0f, 0.0f)); diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index abdd1c2..f32c233 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 conversion */ + kfilm->r_to_xyz = rgb_to_xyz[0]; + kfilm->g_to_xyz = rgb_to_xyz[1]; + kfilm->b_to_xyz = rgb_to_xyz[2]; + kfilm->x_to_rgb = xyz_to_rgb[0]; + kfilm->y_to_rgb = xyz_to_rgb[1]; + kfilm->z_to_rgb = xyz_to_rgb[2]; + need_update = false; } diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h index 966e00a..7d999d6 100644 --- a/intern/cycles/render/film.h +++ b/intern/cycles/render/film.h @@ -59,6 +59,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 * rgb_to_xyz[0] + G * rgb_to_xyz[1] + B * rgb_to_xyz[2]; + */ + float3 xyz_to_rgb[3], rgb_to_xyz[3]; + float mist_start; float mist_depth; float mist_falloff; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 57fb1a7..c78f236 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1662,7 +1662,7 @@ bool ConvertNode::constant_fold(ShaderOutput *socket, float3 *optimized_value) else if(to == SHADER_SOCKET_FLOAT) { if(from == SHADER_SOCKET_COLOR) /* color to float */ - optimized_value->x = linear_rgb_to_gray(value); + return false; /* TODO(lukas): Do correct conversion (depending on color space) here. */ else /* vector/point/normal to float */ optimized_value->x = average(value); @@ -4060,6 +4060,8 @@ BlackbodyNode::BlackbodyNode() bool BlackbodyNode::constant_fold(ShaderOutput *socket, float3 *optimized_value) { + return false; +#if 0 /* TODO(lukas): Fold with correct colorspace here. */ ShaderInput *temperature_in = input("Temperature"); if(socket == output("Color")) { @@ -4071,6 +4073,7 @@ bool BlackbodyNode::constant_fold(ShaderOutput *socket, float3 *optimized_value) } return false; +#endif } void BlackbodyNode::compile(SVMCompiler& compiler) diff --git a/intern/cycles/util/util_color.h b/intern/cycles/util/util_color.h index d3598f8..216d508 100644 --- a/intern/cycles/util/util_color.h +++ b/intern/cycles/util/util_color.h @@ -47,7 +47,7 @@ ccl_device_inline float3 color_byte_to_float(uchar4 c) return make_float3(c.x*(1.0f/255.0f), c.y*(1.0f/255.0f), c.z*(1.0f/255.0f)); } -ccl_device float color_srgb_to_scene_linear(float c) +ccl_device float color_srgb_to_linear(float c) { if(c < 0.04045f) return (c < 0.0f)? 0.0f: c * (1.0f/12.92f); @@ -55,7 +55,7 @@ ccl_device float color_srgb_to_scene_linear(float c) return powf((c + 0.055f) * (1.0f / 1.055f), 2.4f); } -ccl_device float color_scene_linear_to_srgb(float c) +ccl_device float color_linear_to_srgb(float c) { if(c < 0.0031308f) return (c < 0.0f)? 0.0f: c * 12.92f; @@ -150,23 +150,38 @@ ccl_device float3 xyY_to_xyz(float x, float y, float Y) return make_float3(X, Y, Z); } -ccl_device float3 xyz_to_rgb(float x, float y, float z) +ccl_device float3 rec709_to_xyz(float r, float g, float b) +{ + return make_float3(0.412453f * r + 0.357580f * g + 0.180423f * b, + 0.212671f * r + 0.715160f * g + 0.072169f * b, + 0.019334f * r + 0.119194f * g + 0.950227f * b); +} + +ccl_device float3 xyz_to_rec709(float x, float y, float z) { return make_float3(3.240479f * x + -1.537150f * y + -0.498535f * z, -0.969256f * x + 1.875991f * y + 0.041556f * z, 0.055648f * x + -0.204043f * y + 1.057311f * z); } -#ifndef __KERNEL_OPENCL__ +ccl_device float3 xyz_to_rec709(float3 xyz) +{ + return xyz_to_rec709(xyz.x, xyz.y, xyz.z); +} -ccl_device float3 color_srgb_to_scene_linear(float3 c) +ccl_device float3 rec709_to_xyz(float3 rgb) { - return make_float3( - color_srgb_to_scene_linear(c.x), - color_srgb_to_scene_linear(c.y), - color_srgb_to_scene_linear(c.z)); + return rec709_to_xyz(rgb.x, rgb.y, rgb.z); } +#ifndef __KERNEL_OPENCL__ +ccl_device float3 color_srgb_to_linear(float3 c) +{ + return make_float3( + color_srgb_to_linear(c.x), + color_srgb_to_linear(c.y), + color_srgb_to_linear(c.z)); +} #ifdef __KERNEL_SSE2__ /* * Calculate initial guess for arg^exp based on float representation @@ -214,7 +229,7 @@ ccl_device_inline ssef fastpow24(const ssef &arg) return x * (x * x); } -ccl_device ssef color_srgb_to_scene_linear(const ssef &c) +ccl_device ssef color_srgb_to_linear(const ssef &c) { sseb cmp = c < ssef(0.04045f); ssef lt = max(c * ssef(1.0f/12.92f), ssef(0.0f)); @@ -224,21 +239,16 @@ ccl_device ssef color_srgb_to_scene_linear(const ssef &c) } #endif -ccl_device float3 color_scene_linear_to_srgb(float3 c) +ccl_device float3 color_linear_to_srgb(float3 c) { return make_float3( - color_scene_linear_to_srgb(c.x), - color_scene_linear_to_srgb(c.y), - color_scene_linear_to_srgb(c.z)); + color_linear_to_srgb(c.x), + color_linear_to_srgb(c.y), + color_linear_to_srgb(c.z)); } #endif -ccl_device float linear_rgb_to_gray(float3 c) -{ - return c.x*0.2126f + c.y*0.7152f + c.z*0.0722f; -} - CCL_NAMESPACE_END #endif /* __UTIL_COLOR_H__ */ diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 32924f9..046ee0a 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -1546,6 +1546,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