I've limited it to just the RGB<->XYZ stuff for now, correct image handling is the next step.
Reviewers: brecht, sergey
Differential Revision: https://developer.blender.org/D3478
add_definitions(-DWITH_NETWORK)
endif()
+if(WITH_OPENCOLORIO)
+ add_definitions(-DWITH_OCIO)
+ include_directories(
+ SYSTEM
+ ${OPENCOLORIO_INCLUDE_DIRS}
+ )
+endif()
+
if(WITH_CYCLES_STANDALONE OR WITH_CYCLES_NETWORK OR WITH_CYCLES_CUBIN_COMPILER)
add_subdirectory(app)
endif()
if(WITH_CYCLES_OPENSUBDIV)
target_link_libraries(${target} ${OPENSUBDIV_LIBRARIES})
endif()
+ if(WITH_OPENCOLORIO)
+ link_directories(${OPENCOLORIO_LIBPATH})
+ target_link_libraries(${target} ${OPENCOLORIO_LIBRARIES})
+ endif()
target_link_libraries(
${target}
${OPENIMAGEIO_LIBRARIES}
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_v3(CData->curve_vcol[curve]));
+ /* Encode vertex color using the sRGB curve. */
+ cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
vertexindex++;
- cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
+ cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
vertexindex++;
- cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
+ cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
vertexindex++;
- cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
+ cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
vertexindex++;
- cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
+ cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
vertexindex++;
- cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve]));
+ cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
vertexindex++;
}
}
if(fdata) {
size_t i = 0;
+ /* Encode vertex color using the sRGB curve. */
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_v3(CData.curve_vcol[curve]);
+ fdata[i++] = color_srgb_to_linear_v3(CData.curve_vcol[curve]);
}
}
}
int n = p->loop_total();
for(int i = 0; i < n; i++) {
float3 color = get_float3(l->data[p->loop_start() + i].color());
- *(cdata++) = color_float_to_byte(color_srgb_to_scene_linear_v3(color));
+ /* Encode vertex color using the sRGB curve. */
+ *(cdata++) = color_float_to_byte(color_srgb_to_linear_v3(color));
}
}
}
int tri_a[3], tri_b[3];
face_split_tri_indices(face_flags[i], tri_a, tri_b);
+ /* Encode vertex color using the sRGB curve. */
uchar4 colors[4];
- colors[0] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color1())));
- colors[1] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color2())));
- colors[2] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color3())));
+ colors[0] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color1())));
+ colors[1] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color2())));
+ colors[2] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color3())));
if(nverts[i] == 4) {
- colors[3] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color4())));
+ colors[3] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color4())));
}
cdata[0] = colors[tri_a[0]];
scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4, _5);
scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3, _4, _5);
+#ifdef WITH_OCIO
+ scene->film->set_color_config(OCIO_getCurrentConfig());
+#endif
+
session->scene = scene;
/* create sync */
find_package(LLVM REQUIRED)
endif()
+ ####
+ # OpenColorIO
+ if(WITH_OPENCOLORIO)
+ find_package(OpenColorIO REQUIRED)
+ endif()
+
####
# Boost
set(__boost_packages filesystem regex system thread date_time)
--- /dev/null
+/*
+ * Copyright 2011-2018 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __KERNEL_COLOR_H__
+#define __KERNEL_COLOR_H__
+
+#include "util/util_color.h"
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device float3 xyz_to_rgb(KernelGlobals *kg, float3 xyz)
+{
+ return make_float3(dot(kernel_data.film.xyz_to_r, xyz),
+ dot(kernel_data.film.xyz_to_g, xyz),
+ dot(kernel_data.film.xyz_to_b, xyz));
+}
+
+ccl_device float linear_rgb_to_gray(KernelGlobals *kg, float3 c)
+{
+ return dot(c, kernel_data.film.rgb_to_y);
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __KERNEL_COLOR_H__ */
\ No newline at end of file
float4 result = irradiance*scale;
/* 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);
+ 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);
/* clamp since alpha might be > 1.0 due to russian roulette */
result.w = saturate(result.w);
int pass_denoising_clean;
int denoising_flags;
+ float3 xyz_to_r;
+ float3 xyz_to_g;
+ float3 xyz_to_b;
+ float3 rgb_to_y;
+
int pad1, pad2, pad3;
#ifdef __KERNEL_DEBUG__
# include "kernel/split/kernel_split_data.h"
# include "kernel/kernel_globals.h"
+# include "kernel/kernel_color.h"
# include "kernel/kernels/cpu/kernel_cpu_image.h"
# include "kernel/kernel_film.h"
# include "kernel/kernel_path.h"
#include "kernel/kernel_math.h"
#include "kernel/kernel_types.h"
#include "kernel/kernel_globals.h"
+#include "kernel/kernel_color.h"
#include "kernel/kernels/cuda/kernel_cuda_image.h"
#include "kernel/kernel_film.h"
#include "kernel/kernel_path.h"
#include "kernel/kernel_math.h"
#include "kernel/kernel_types.h"
#include "kernel/kernel_globals.h"
+#include "kernel/kernel_color.h"
#include "kernel/kernels/opencl/kernel_opencl_image.h"
#include "kernel/kernel_film.h"
#include "kernel/kernel_compat_cpu.h"
#include "kernel/split/kernel_split_data_types.h"
#include "kernel/kernel_globals.h"
+#include "kernel/kernel_color.h"
#include "kernel/kernel_random.h"
#include "kernel/kernel_projection.h"
#include "kernel/kernel_differential.h"
* limitations under the License.
*/
+/* TODO(lukas): Fix colors in OSL. */
+
float color_srgb_to_scene_linear(float c)
{
if (c < 0.04045)
#include "kernel/split/kernel_split_data.h"
#include "kernel/kernel_globals.h"
+#include "kernel/kernel_color.h"
#ifdef __OSL__
# include "kernel/osl/osl_shader.h"
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);
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);
/* sheen */
if(diffuse_weight > CLOSURE_WEIGHT_CUTOFF && sheen > CLOSURE_WEIGHT_CUTOFF) {
- float m_cdlum = linear_rgb_to_gray(base_color);
+ float m_cdlum = linear_rgb_to_gray(kg, base_color);
float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
/* color of the sheen component */
/* 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: {
}
case NODE_CONVERT_CF: {
float3 f = stack_load_float3(stack, from);
- float g = linear_rgb_to_gray(f);
+ float g = linear_rgb_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)linear_rgb_to_gray(kg, f);
stack_store_int(stack, to, i);
break;
}
}
if(srgb) {
- r = color_srgb_to_scene_linear_v4(r);
+ /* TODO(lukas): Implement proper conversion for image textures. */
+ r = color_srgb_to_linear_v4(r);
}
return r;
ccl_device float3 svm_math_blackbody_color(float t)
{
+ /* TODO(lukas): Reimplement in XYZ. */
+
if(t >= 12000.0f) {
return make_float3(0.826270103f, 0.994478524f, 1.56626022f);
}
/* convert to RGB */
float3 xyz = xyY_to_xyz(x, y, Y);
- return xyz_to_rgb(xyz.x, xyz.y, xyz.z);
+ return xyz_to_rgb(kg, xyz);
}
/*
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_rgb(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)
{0.0001f,0.0000f,0.0000f}, {0.0001f,0.0000f,0.0000f}, {0.0000f,0.0000f,0.0000f}
};
-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)
{
float lambda_nm = stack_load_float(stack, wavelength);
float ii = (lambda_nm-380.0f) * (1.0f/5.0f); // scaled 0..80
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 = xyz_to_rgb(kg, color);
color *= 1.0f/2.52f; // Empirical scale from lg to make all comps <= 1
/* Clamp to zero if values are smaller */
CCL_NAMESPACE_BEGIN
-ConstantFolder::ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output)
-: graph(graph), node(node), output(output)
+ConstantFolder::ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output, Scene *scene)
+: graph(graph), node(node), output(output), scene(scene)
{
}
CCL_NAMESPACE_BEGIN
+class Scene;
class ShaderGraph;
class ShaderInput;
class ShaderNode;
ShaderNode *const node;
ShaderOutput *const output;
- ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output);
+ Scene *scene;
+
+ ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output, Scene *scene);
bool all_inputs_constant() const;
* Try to constant fold some nodes, and pipe result directly to
* the input socket of connected nodes.
*/
-void ShaderGraph::constant_fold()
+void ShaderGraph::constant_fold(Scene *scene)
{
ShaderNodeSet done, scheduled;
queue<ShaderNode*> traverse_queue;
}
}
/* Optimize current node. */
- ConstantFolder folder(this, node, output);
+ ConstantFolder folder(this, node, output, scene);
node->constant_fold(folder);
}
}
/* Graph simplification */
/* NOTE: Remove proxy nodes was already done. */
- constant_fold();
+ constant_fold(scene);
simplify_settings(scene);
deduplicate_nodes();
verify_volume_output();
/* Graph simplification routines. */
void clean(Scene *scene);
- void constant_fold();
+ void constant_fold(Scene *scene);
void simplify_settings(Scene *scene);
void deduplicate_nodes();
void verify_volume_output();
* limitations under the License.
*/
+#include "render/film.h"
#include "render/image.h"
#include "render/integrator.h"
#include "render/light.h"
void RGBToBWNode::constant_fold(const ConstantFolder& folder)
{
if(folder.all_inputs_constant()) {
- folder.make_constant(linear_rgb_to_gray(color));
+ float val = folder.scene->shader_manager->linear_rgb_to_gray(color);
+ folder.make_constant(val);
}
}
if(to == SocketType::FLOAT) {
if(from == SocketType::COLOR) {
/* color to float */
- folder.make_constant(linear_rgb_to_gray(value_color));
+ float val = folder.scene->shader_manager->linear_rgb_to_gray(value_color);
+ folder.make_constant(val);
}
else {
/* vector/point/normal to float */
#include "util/util_foreach.h"
+#ifdef WITH_OCIO
+# include <OpenColorIO/OpenColorIO.h>
+namespace OCIO = OCIO_NAMESPACE;
+#endif
+
CCL_NAMESPACE_BEGIN
thread_mutex ShaderManager::lookup_table_mutex;
{
need_update = true;
beckmann_table_offset = TABLE_OFFSET_INVALID;
+
+ 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);
+ rgb_to_y = make_float3( 0.2126729f, 0.7151522f, 0.0721750f);
+
+#ifdef WITH_OCIO
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ if(config) {
+ if(config->hasRole("XYZ") && config->hasRole("scene_linear")) {
+ OCIO::ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear");
+ OCIO::ConstProcessorRcPtr to_xyz_processor = config->getProcessor("scene_linear", "XYZ");
+ if(to_rgb_processor && to_xyz_processor) {
+ float r[] = {1.0f, 0.0f, 0.0f};
+ float g[] = {0.0f, 1.0f, 0.0f};
+ float b[] = {0.0f, 0.0f, 1.0f};
+ to_xyz_processor->applyRGB(r);
+ to_xyz_processor->applyRGB(g);
+ to_xyz_processor->applyRGB(b);
+ rgb_to_y = make_float3(r[1], g[1], b[1]);
+
+ float x[] = {1.0f, 0.0f, 0.0f};
+ float y[] = {0.0f, 1.0f, 0.0f};
+ float z[] = {0.0f, 0.0f, 1.0f};
+ to_rgb_processor->applyRGB(x);
+ to_rgb_processor->applyRGB(y);
+ to_rgb_processor->applyRGB(z);
+ xyz_to_r = make_float3(x[0], y[0], z[0]);
+ xyz_to_g = make_float3(x[1], y[1], z[1]);
+ xyz_to_b = make_float3(x[2], y[2], z[2]);
+ }
+ }
+ }
+#endif
}
ShaderManager::~ShaderManager()
kintegrator->use_volumes = has_volumes;
/* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
kintegrator->transparent_shadows = has_transparent_shadow;
+
+ /* film */
+ KernelFilm *kfilm = &dscene->data.film;
+ /* color space, needs to be here because e.g. displacement shaders could depend on it */
+ kfilm->xyz_to_r = xyz_to_r;
+ kfilm->xyz_to_g = xyz_to_g;
+ kfilm->xyz_to_b = xyz_to_b;
+ kfilm->rgb_to_y = rgb_to_y;
}
void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene)
beckmann_table.free_memory();
}
+float ShaderManager::linear_rgb_to_gray(float3 c)
+{
+ return dot(c, rgb_to_y);
+}
+
CCL_NAMESPACE_END
static void free_memory();
+ float linear_rgb_to_gray(float3 c);
+
protected:
ShaderManager();
DeviceRequestedFeatures *requested_features);
thread_spin_lock attribute_lock_;
+
+ float3 xyz_to_r;
+ float3 xyz_to_g;
+ float3 xyz_to_b;
+ float3 rgb_to_y;
};
CCL_NAMESPACE_END
${LLVM_LIBRARIES}
)
endif()
+if(WITH_OPENCOLORIO)
+ list(APPEND ALL_CYCLES_LIBRARIES
+ ${OPENCOLORIO_LIBRARIES}
+ )
+endif()
if(WITH_IMAGE_OPENJPEG)
if(WITH_SYSTEM_OPENJPEG)
list(APPEND ALL_CYCLES_LIBRARIES ${OPENJPEG_LIBRARIES})
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);
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;
return make_float3(X, Y, Z);
}
-ccl_device float3 xyz_to_rgb(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);
-}
-
#ifdef __KERNEL_SSE2__
/*
* Calculate initial guess for arg^exp based on float representation
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));
}
#endif /* __KERNEL_SSE2__ */
-ccl_device float3 color_srgb_to_scene_linear_v3(float3 c)
+ccl_device float3 color_srgb_to_linear_v3(float3 c)
{
- 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 make_float3(color_srgb_to_linear(c.x),
+ color_srgb_to_linear(c.y),
+ color_srgb_to_linear(c.z));
}
-ccl_device float3 color_scene_linear_to_srgb_v3(float3 c)
+ccl_device float3 color_linear_to_srgb_v3(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));
+ return make_float3(color_linear_to_srgb(c.x),
+ color_linear_to_srgb(c.y),
+ color_linear_to_srgb(c.z));
}
-ccl_device float4 color_srgb_to_scene_linear_v4(float4 c)
+ccl_device float4 color_srgb_to_linear_v4(float4 c)
{
#ifdef __KERNEL_SSE2__
ssef r_ssef;
float4 &r = (float4 &)r_ssef;
r = c;
- r_ssef = color_srgb_to_scene_linear(r_ssef);
+ r_ssef = color_srgb_to_linear(r_ssef);
r.w = c.w;
return r;
#else
- return make_float4(color_srgb_to_scene_linear(c.x),
- color_srgb_to_scene_linear(c.y),
- color_srgb_to_scene_linear(c.z),
+ return make_float4(color_srgb_to_linear(c.x),
+ color_srgb_to_linear(c.y),
+ color_srgb_to_linear(c.z),
c.w);
#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__ */
# Non-color data
data: Non-Color
+ # CIE XYZ color space
+ XYZ: XYZ
+
displays:
sRGB:
- !<View> {name: Default, colorspace: sRGB}
allocationvars: [-8.5, 5]
from_reference: !<GroupTransform>
children:
- - !<FileTransform> {src: rec709_to_aces.spimtx, interpolation: linear}
- - !<FileTransform> {src: aces_to_xyz.spimtx, interpolation: linear}
+ - !<FileTransform> {src: srgb_to_xyz.spimtx, interpolation: linear}
- !<ColorSpace>
name: rrt_xyz