diff options
Diffstat (limited to 'intern/cycles')
40 files changed, 380 insertions, 174 deletions
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 100a52625d1..233bc639fd8 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -326,6 +326,14 @@ if(WITH_CYCLES_NETWORK) 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() diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt index d1f86a5fe7d..cfca45600a5 100644 --- a/intern/cycles/app/CMakeLists.txt +++ b/intern/cycles/app/CMakeLists.txt @@ -80,6 +80,10 @@ macro(cycles_target_link_libraries target) 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} diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 3b79b6e52fd..df6949f2095 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -128,6 +128,12 @@ enum_volume_interpolation = ( ('CUBIC', "Cubic", "Smoothed high quality interpolation, but slower") ) +enum_world_mis = ( + ('NONE', "None", "Don't sample the background, faster but might cause noise for non-solid backgrounds"), + ('AUTOMATIC', "Auto", "Automatically try to determine the best setting"), + ('MANUAL', "Manual", "Manually set the resolution of the sampling map, higher values are slower and require more memory but reduce noise") + ) + enum_device_type = ( ('CPU', "CPU", "CPU", 0), ('CUDA', "CUDA", "CUDA", 1), @@ -932,15 +938,15 @@ class CyclesWorldSettings(bpy.types.PropertyGroup): description="Cycles world settings", type=cls, ) - cls.sample_as_light = BoolProperty( - name="Multiple Importance Sample", - description="Use multiple importance sampling for the environment, " - "enabling for non-solid colors is recommended", - default=True, + cls.sampling_method = EnumProperty( + name="Sampling method", + description="How to sample the background light", + items=enum_world_mis, + default='AUTOMATIC', ) cls.sample_map_resolution = IntProperty( name="Map Resolution", - description="Importance map size is resolution x resolution; " + description="Importance map size is resolution x resolution/2; " "higher values potentially produce less noise, at the cost of memory and speed", min=4, max=8192, default=1024, diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index c5eafe9ebfb..2f9c486367a 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1367,11 +1367,13 @@ class CYCLES_WORLD_PT_settings_surface(CyclesButtonsPanel, Panel): cworld = world.cycles col = layout.column() - col.prop(cworld, "sample_as_light", text="Multiple Importance") + col.prop(cworld, "sampling_method", text="Sampling") sub = col.column() - sub.active = cworld.sample_as_light - sub.prop(cworld, "sample_map_resolution") + sub.active = cworld.sampling_method != 'NONE' + subsub = sub.row(align=True) + subsub.active = cworld.sampling_method == 'MANUAL' + subsub.prop(cworld, "sample_map_resolution") if use_branched_path(context): subsub = sub.column(align=True) subsub.active = use_sample_all_lights(context) diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py index 611ba5cae70..2db4def9dcb 100644 --- a/intern/cycles/blender/addon/version_update.py +++ b/intern/cycles/blender/addon/version_update.py @@ -377,10 +377,6 @@ def do_versions(self): for world in bpy.data.worlds: cworld = world.cycles - # World MIS - if not cworld.is_property_set("sample_as_light"): - cworld.sample_as_light = False - # World MIS Samples if not cworld.is_property_set("samples"): cworld.samples = 4 @@ -444,3 +440,12 @@ def do_versions(self): part.tip_radius = cpart.get("tip_width", 0.0) part.radius_scale = cpart.get("radius_scale", 0.01) part.use_close_tip = cpart.get("use_closetip", True) + + for world in bpy.data.worlds: + cworld = world.cycles + # World MIS + if not cworld.is_property_set("sampling_method"): + if cworld.get("sample_as_light", False): + cworld.sampling_method = 'MANUAL' + else: + cworld.sampling_method = 'NONE' diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index e9270ee5539..a1fd153b4fd 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -770,17 +770,18 @@ static void ExportCurveTriangleVcol(ParticleCurveData *CData, 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++; } } @@ -993,9 +994,10 @@ void BlenderSync::sync_curves(Mesh *mesh, 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]); } } } diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 6fe650f3699..b7d6c1bb36d 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -401,7 +401,8 @@ static void attr_create_vertex_color(Scene *scene, 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)); } } } @@ -424,12 +425,13 @@ static void attr_create_vertex_color(Scene *scene, 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]]; diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index dbeab2fdf61..e0737d5118a 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -242,7 +242,15 @@ void BlenderSync::sync_background_light(bool use_portal) if(b_world) { PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles"); - bool sample_as_light = get_boolean(cworld, "sample_as_light"); + + enum SamplingMethod { + SAMPLING_NONE = 0, + SAMPLING_AUTOMATIC, + SAMPLING_MANUAL, + SAMPLING_NUM + }; + int sampling_method = get_enum(cworld, "sampling_method", SAMPLING_NUM, SAMPLING_AUTOMATIC); + bool sample_as_light = (sampling_method != SAMPLING_NONE); if(sample_as_light || use_portal) { /* test if we need to sync */ @@ -254,7 +262,12 @@ void BlenderSync::sync_background_light(bool use_portal) b_world.ptr.data != world_map) { light->type = LIGHT_BACKGROUND; - light->map_resolution = get_int(cworld, "sample_map_resolution"); + if(sampling_method == SAMPLING_MANUAL) { + light->map_resolution = get_int(cworld, "sample_map_resolution"); + } + else { + light->map_resolution = 0; + } light->shader = scene->default_background; light->use_mis = sample_as_light; light->max_bounces = get_int(cworld, "max_bounces"); diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index eec13d04d7d..8e76a4c0061 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -141,6 +141,10 @@ void BlenderSession::create_session() 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; /* There is no single depsgraph to use for the entire render. diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index 8d04025e6fd..2e386a6bfc5 100644 --- a/intern/cycles/cmake/external_libs.cmake +++ b/intern/cycles/cmake/external_libs.cmake @@ -98,6 +98,12 @@ if(CYCLES_STANDALONE_REPOSITORY) endif() #### + # OpenColorIO + if(WITH_OPENCOLORIO) + find_package(OpenColorIO REQUIRED) + endif() + + #### # Boost set(__boost_packages filesystem regex system thread date_time) if(WITH_CYCLES_NETWORK) diff --git a/intern/cycles/kernel/kernel_color.h b/intern/cycles/kernel/kernel_color.h new file mode 100644 index 00000000000..d1c3dac824d --- /dev/null +++ b/intern/cycles/kernel/kernel_color.h @@ -0,0 +1,38 @@ +/* + * 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 diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index a5556c3be8f..524e2467ebc 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -319,9 +319,9 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg, #ifdef __BACKGROUND_MIS__ /* check if background light exists or if we should skip pdf */ - int res = kernel_data.integrator.pdf_background_res; + int res_x = kernel_data.integrator.pdf_background_res_x; - if(!(state->flag & PATH_RAY_MIS_SKIP) && res) { + if(!(state->flag & PATH_RAY_MIS_SKIP) && res_x) { /* multiple importance sampling, get background light pdf for ray * direction, and compute weight with respect to BSDF pdf */ float pdf = background_light_pdf(kg, ray->P, ray->D); diff --git a/intern/cycles/kernel/kernel_film.h b/intern/cycles/kernel/kernel_film.h index f9e9b413898..94815601179 100644 --- a/intern/cycles/kernel/kernel_film.h +++ b/intern/cycles/kernel/kernel_film.h @@ -22,9 +22,9 @@ ccl_device float4 film_map(KernelGlobals *kg, float4 irradiance, float scale) 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); diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index b1be0b2155a..32cb924d25f 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -197,12 +197,13 @@ float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float /* for the following, the CDF values are actually a pair of floats, with the * function value as X and the actual CDF as Y. The last entry's function * value is the CDF total. */ - int res = kernel_data.integrator.pdf_background_res; - int cdf_count = res + 1; + int res_x = kernel_data.integrator.pdf_background_res_x; + int res_y = kernel_data.integrator.pdf_background_res_y; + int cdf_width = res_x + 1; /* this is basically std::lower_bound as used by pbrt */ int first = 0; - int count = res; + int count = res_y; while(count > 0) { int step = count >> 1; @@ -217,24 +218,24 @@ float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float } int index_v = max(0, first - 1); - kernel_assert(index_v >= 0 && index_v < res); + kernel_assert(index_v >= 0 && index_v < res_y); float2 cdf_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v); float2 cdf_next_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v + 1); - float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res); + float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res_y); /* importance-sampled V direction */ float dv = inverse_lerp(cdf_v.y, cdf_next_v.y, randv); - float v = (index_v + dv) / res; + float v = (index_v + dv) / res_y; /* this is basically std::lower_bound as used by pbrt */ first = 0; - count = res; + count = res_x; while(count > 0) { int step = count >> 1; int middle = first + step; - if(kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_count + middle).y < randu) { + if(kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + middle).y < randu) { first = middle + 1; count -= step + 1; } @@ -243,15 +244,15 @@ float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float } int index_u = max(0, first - 1); - kernel_assert(index_u >= 0 && index_u < res); + kernel_assert(index_u >= 0 && index_u < res_x); - float2 cdf_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_count + index_u); - float2 cdf_next_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_count + index_u + 1); - float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_count + res); + float2 cdf_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + index_u); + float2 cdf_next_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + index_u + 1); + float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + res_x); /* importance-sampled U direction */ float du = inverse_lerp(cdf_u.y, cdf_next_u.y, randu); - float u = (index_u + du) / res; + float u = (index_u + du) / res_x; /* compute pdf */ float denom = cdf_last_u.x * cdf_last_v.x; @@ -277,19 +278,21 @@ ccl_device float background_map_pdf(KernelGlobals *kg, float3 direction) { float2 uv = direction_to_equirectangular(direction); - int res = kernel_data.integrator.pdf_background_res; + int res_x = kernel_data.integrator.pdf_background_res_x; + int res_y = kernel_data.integrator.pdf_background_res_y; + int cdf_width = res_x + 1; float sin_theta = sinf(uv.y * M_PI_F); if(sin_theta == 0.0f) return 0.0f; - int index_u = clamp(float_to_int(uv.x * res), 0, res - 1); - int index_v = clamp(float_to_int(uv.y * res), 0, res - 1); + int index_u = clamp(float_to_int(uv.x * res_x), 0, res_x - 1); + int index_v = clamp(float_to_int(uv.y * res_y), 0, res_y - 1); /* pdfs in V direction */ - float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * (res + 1) + res); - float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res); + float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + res_x); + float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res_y); float denom = cdf_last_u.x * cdf_last_v.x; @@ -297,7 +300,7 @@ float background_map_pdf(KernelGlobals *kg, float3 direction) return 0.0f; /* pdfs in U direction */ - float2 cdf_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * (res + 1) + index_u); + float2 cdf_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + index_u); float2 cdf_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v); return (cdf_u.x * cdf_v.x)/(M_2PI_F * M_PI_F * sin_theta * denom); diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 72fbf7be557..633518c7926 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -1272,6 +1272,11 @@ typedef struct KernelFilm { 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__ @@ -1306,7 +1311,8 @@ typedef struct KernelIntegrator { int num_all_lights; float pdf_triangles; float pdf_lights; - int pdf_background_res; + int pdf_background_res_x; + int pdf_background_res_y; float light_inv_rr_threshold; /* light portals */ @@ -1368,6 +1374,8 @@ typedef struct KernelIntegrator { int start_sample; int max_closures; + + int pad1, pad2, pad3; } KernelIntegrator; static_assert_align(KernelIntegrator, 16); diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h index ccca023a15f..5ec1655ab05 100644 --- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h +++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h @@ -30,6 +30,7 @@ # 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" diff --git a/intern/cycles/kernel/kernels/cuda/kernel.cu b/intern/cycles/kernel/kernels/cuda/kernel.cu index 3c93e00ccf1..8a180a509e8 100644 --- a/intern/cycles/kernel/kernels/cuda/kernel.cu +++ b/intern/cycles/kernel/kernels/cuda/kernel.cu @@ -26,6 +26,7 @@ #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" diff --git a/intern/cycles/kernel/kernels/opencl/kernel.cl b/intern/cycles/kernel/kernels/opencl/kernel.cl index 9d5d784e140..63128d0aecf 100644 --- a/intern/cycles/kernel/kernels/opencl/kernel.cl +++ b/intern/cycles/kernel/kernels/opencl/kernel.cl @@ -20,6 +20,7 @@ #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" diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 5f4baf6fda3..1aca54d2ad5 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -41,6 +41,7 @@ #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" diff --git a/intern/cycles/kernel/shaders/node_color.h b/intern/cycles/kernel/shaders/node_color.h index 4a17286a07f..2c3a810cb18 100644 --- a/intern/cycles/kernel/shaders/node_color.h +++ b/intern/cycles/kernel/shaders/node_color.h @@ -14,6 +14,8 @@ * limitations under the License. */ +/* TODO(lukas): Fix colors in OSL. */ + float color_srgb_to_scene_linear(float c) { if (c < 0.04045) diff --git a/intern/cycles/kernel/split/kernel_split_common.h b/intern/cycles/kernel/split/kernel_split_common.h index abe68104449..4b86696691a 100644 --- a/intern/cycles/kernel/split/kernel_split_common.h +++ b/intern/cycles/kernel/split/kernel_split_common.h @@ -23,6 +23,7 @@ #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" diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index bfa146f2d93..ce2affe96c8 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -243,7 +243,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); @@ -465,7 +465,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_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 886a1333fa3..76464e37c66 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -217,7 +217,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float * /* 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 */ diff --git a/intern/cycles/kernel/svm/svm_convert.h b/intern/cycles/kernel/svm/svm_convert.h index 34080377083..c88ac57e20d 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 = 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; } diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index 4226e7adfe0..28565308867 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -33,7 +33,8 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, } 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; diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h index 8e6bc73ddc7..caf0addbf35 100644 --- a/intern/cycles/kernel/svm/svm_math_util.h +++ b/intern/cycles/kernel/svm/svm_math_util.h @@ -138,6 +138,8 @@ ccl_static_constant float blackbody_table_b[6][4] = { 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); } diff --git a/intern/cycles/kernel/svm/svm_sky.h b/intern/cycles/kernel/svm/svm_sky.h index 854e85fd326..b83a7168541 100644 --- a/intern/cycles/kernel/svm/svm_sky.h +++ b/intern/cycles/kernel/svm/svm_sky.h @@ -59,7 +59,7 @@ ccl_device float3 sky_radiance_old(KernelGlobals *kg, float3 dir, /* 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); } /* @@ -102,7 +102,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_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) diff --git a/intern/cycles/kernel/svm/svm_wavelength.h b/intern/cycles/kernel/svm/svm_wavelength.h index 855b356b397..62e026278ac 100644 --- a/intern/cycles/kernel/svm/svm_wavelength.h +++ b/intern/cycles/kernel/svm/svm_wavelength.h @@ -70,7 +70,7 @@ ccl_static_constant float cie_colour_match[81][3] = { {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 @@ -86,7 +86,7 @@ ccl_device void svm_node_wavelength(ShaderData *sd, float *stack, uint wavelengt 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 */ diff --git a/intern/cycles/render/constant_fold.cpp b/intern/cycles/render/constant_fold.cpp index 943b218f0e4..98c3e99996c 100644 --- a/intern/cycles/render/constant_fold.cpp +++ b/intern/cycles/render/constant_fold.cpp @@ -22,8 +22,8 @@ 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) { } diff --git a/intern/cycles/render/constant_fold.h b/intern/cycles/render/constant_fold.h index 33f93b8c0ab..cc24d614206 100644 --- a/intern/cycles/render/constant_fold.h +++ b/intern/cycles/render/constant_fold.h @@ -22,6 +22,7 @@ CCL_NAMESPACE_BEGIN +class Scene; class ShaderGraph; class ShaderInput; class ShaderNode; @@ -33,7 +34,9 @@ public: 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; diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index dca168824d9..8b179f742c4 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -243,18 +243,27 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to) /* add automatic conversion node in case of type mismatch */ ShaderNode *convert; + ShaderInput *convert_in; if (to->type() == SocketType::CLOSURE) { EmissionNode *emission = new EmissionNode(); emission->color = make_float3(1.0f, 1.0f, 1.0f); emission->strength = 1.0f; convert = add(emission); + /* Connect float inputs to Strength to save an additional Falue->Color conversion. */ + if(from->type() == SocketType::FLOAT) { + convert_in = convert->input("Strength"); + } + else { + convert_in = convert->input("Color"); + } } else { convert = add(new ConvertNode(from->type(), to->type(), true)); + convert_in = convert->inputs[0]; } - connect(from, convert->inputs[0]); + connect(from, convert_in); connect(convert->outputs[0], to); } else { @@ -487,7 +496,7 @@ void ShaderGraph::remove_proxy_nodes() * 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; @@ -527,7 +536,7 @@ void ShaderGraph::constant_fold() } } /* Optimize current node. */ - ConstantFolder folder(this, node, output); + ConstantFolder folder(this, node, output, scene); node->constant_fold(folder); } } @@ -725,7 +734,7 @@ void ShaderGraph::clean(Scene *scene) /* Graph simplification */ /* NOTE: Remove proxy nodes was already done. */ - constant_fold(); + constant_fold(scene); simplify_settings(scene); deduplicate_nodes(); verify_volume_output(); diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 2c134932b3c..5d986ae4827 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -285,7 +285,7 @@ protected: /* 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(); diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 6867ea95d63..023ca4b47c2 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -94,6 +94,25 @@ device_memory *ImageManager::image_memory(int flat_slot) return img->mem; } +bool ImageManager::get_image_metadata(int flat_slot, + ImageMetaData& metadata) +{ + if(flat_slot == -1) { + return false; + } + + ImageDataType type; + int slot = flattened_slot_to_type_index(flat_slot, &type); + + Image *img = images[type][slot]; + if(img) { + metadata = img->metadata; + return true; + } + + return false; +} + bool ImageManager::get_image_metadata(const string& filename, void *builtin_data, ImageMetaData& metadata) @@ -329,7 +348,7 @@ int ImageManager::add_image(const string& filename, img = new Image(); img->filename = filename; img->builtin_data = builtin_data; - img->builtin_free_cache = metadata.builtin_free_cache; + img->metadata = metadata; img->need_load = true; img->animated = animated; img->frame = frame; @@ -417,11 +436,7 @@ void ImageManager::tag_reload_image(const string& filename, } bool ImageManager::file_load_image_generic(Image *img, - ImageInput **in, - int &width, - int &height, - int &depth, - int &components) + ImageInput **in) { if(img->filename == "") return false; @@ -449,28 +464,15 @@ bool ImageManager::file_load_image_generic(Image *img, *in = NULL; return false; } - - width = spec.width; - height = spec.height; - depth = spec.depth; - components = spec.nchannels; } else { /* load image using builtin images callbacks */ if(!builtin_image_info_cb || !builtin_image_pixels_cb) return false; - - ImageMetaData metadata; - builtin_image_info_cb(img->filename, img->builtin_data, metadata); - - width = metadata.width; - height = metadata.height; - depth = metadata.depth; - components = metadata.channels; } /* we only handle certain number of components */ - if(!(components >= 1 && components <= 4)) { + if(!(img->metadata.channels >= 1 && img->metadata.channels <= 4)) { if(*in) { (*in)->close(); delete *in; @@ -493,10 +495,16 @@ bool ImageManager::file_load_image(Image *img, { const StorageType alpha_one = (FileFormat == TypeDesc::UINT8)? 255 : 1; ImageInput *in = NULL; - int width, height, depth, components; - if(!file_load_image_generic(img, &in, width, height, depth, components)) { + if(!file_load_image_generic(img, &in)) { return false; } + + /* Get metadata. */ + int width = img->metadata.width; + int height = img->metadata.height; + int depth = img->metadata.depth; + int components = img->metadata.channels; + /* Read RGBA pixels. */ vector<StorageType> pixels_storage; StorageType *pixels; @@ -557,14 +565,14 @@ bool ImageManager::file_load_image(Image *img, img->builtin_data, (float*)&pixels[0], num_pixels * components, - img->builtin_free_cache); + img->metadata.builtin_free_cache); } else if(FileFormat == TypeDesc::UINT8) { builtin_image_pixels_cb(img->filename, img->builtin_data, (uchar*)&pixels[0], num_pixels * components, - img->builtin_free_cache); + img->metadata.builtin_free_cache); } else { /* TODO(dingto): Support half for ImBuf. */ diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 66f929aa03a..59b9f9ea28d 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -71,6 +71,8 @@ public: bool get_image_metadata(const string& filename, void *builtin_data, ImageMetaData& metadata); + bool get_image_metadata(int flat_slot, + ImageMetaData& metadata); void device_update(Device *device, Scene *scene, @@ -114,7 +116,7 @@ public: struct Image { string filename; void *builtin_data; - bool builtin_free_cache; + ImageMetaData metadata; bool use_alpha; bool need_load; @@ -141,11 +143,7 @@ private: void *osl_texture_system; bool file_load_image_generic(Image *img, - ImageInput **in, - int &width, - int &height, - int &depth, - int &components); + ImageInput **in); template<TypeDesc::BASETYPE FileFormat, typename StorageType, diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index d45d4543e16..5a58ef1aa8e 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -18,8 +18,10 @@ #include "device/device.h" #include "render/integrator.h" #include "render/film.h" +#include "render/graph.h" #include "render/light.h" #include "render/mesh.h" +#include "render/nodes.h" #include "render/object.h" #include "render/scene.h" #include "render/shader.h" @@ -32,12 +34,9 @@ CCL_NAMESPACE_BEGIN -static void shade_background_pixels(Device *device, DeviceScene *dscene, int res, vector<float3>& pixels, Progress& progress) +static void shade_background_pixels(Device *device, DeviceScene *dscene, int width, int height, vector<float3>& pixels, Progress& progress) { /* create input */ - int width = res; - int height = res; - device_vector<uint4> d_input(device, "background_input", MEM_READ_ONLY); device_vector<float4> d_output(device, "background_output", MEM_READ_WRITE); @@ -121,7 +120,7 @@ NODE_DEFINE(Light) SOCKET_FLOAT(sizev, "Size V", 1.0f); SOCKET_BOOLEAN(round, "Round", false); - SOCKET_INT(map_resolution, "Map Resolution", 512); + SOCKET_INT(map_resolution, "Map Resolution", 0); SOCKET_FLOAT(spot_angle, "Spot Angle", M_PI_4_F); SOCKET_FLOAT(spot_smooth, "Spot Smooth", 0.0f); @@ -482,40 +481,41 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce static void background_cdf(int start, int end, - int res, - int cdf_count, + int res_x, + int res_y, const vector<float3> *pixels, float2 *cond_cdf) { + int cdf_width = res_x+1; /* Conditional CDFs (rows, U direction). */ for(int i = start; i < end; i++) { - float sin_theta = sinf(M_PI_F * (i + 0.5f) / res); - float3 env_color = (*pixels)[i * res]; + float sin_theta = sinf(M_PI_F * (i + 0.5f) / res_y); + float3 env_color = (*pixels)[i * res_x]; float ave_luminance = average(env_color); - cond_cdf[i * cdf_count].x = ave_luminance * sin_theta; - cond_cdf[i * cdf_count].y = 0.0f; + cond_cdf[i * cdf_width].x = ave_luminance * sin_theta; + cond_cdf[i * cdf_width].y = 0.0f; - for(int j = 1; j < res; j++) { - env_color = (*pixels)[i * res + j]; + for(int j = 1; j < res_x; j++) { + env_color = (*pixels)[i * res_x + j]; ave_luminance = average(env_color); - cond_cdf[i * cdf_count + j].x = ave_luminance * sin_theta; - cond_cdf[i * cdf_count + j].y = cond_cdf[i * cdf_count + j - 1].y + cond_cdf[i * cdf_count + j - 1].x / res; + cond_cdf[i * cdf_width + j].x = ave_luminance * sin_theta; + cond_cdf[i * cdf_width + j].y = cond_cdf[i * cdf_width + j - 1].y + cond_cdf[i * cdf_width + j - 1].x / res_x; } - float cdf_total = cond_cdf[i * cdf_count + res - 1].y + cond_cdf[i * cdf_count + res - 1].x / res; + float cdf_total = cond_cdf[i * cdf_width + res_x - 1].y + cond_cdf[i * cdf_width + res_x - 1].x / res_x; float cdf_total_inv = 1.0f / cdf_total; /* stuff the total into the brightness value for the last entry, because * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */ - cond_cdf[i * cdf_count + res].x = cdf_total; + cond_cdf[i * cdf_width + res_x].x = cdf_total; if(cdf_total > 0.0f) - for(int j = 1; j < res; j++) - cond_cdf[i * cdf_count + j].y *= cdf_total_inv; + for(int j = 1; j < res_x; j++) + cond_cdf[i * cdf_width + j].y *= cdf_total_inv; - cond_cdf[i * cdf_count + res].y = 1.0f; + cond_cdf[i * cdf_width + res_x].y = 1.0f; } } @@ -537,7 +537,8 @@ void LightManager::device_update_background(Device *device, /* no background light found, signal renderer to skip sampling */ if(!background_light || !background_light->is_enabled) { - kintegrator->pdf_background_res = 0; + kintegrator->pdf_background_res_x = 0; + kintegrator->pdf_background_res_y = 0; return; } @@ -546,41 +547,62 @@ void LightManager::device_update_background(Device *device, assert(kintegrator->use_direct_light); /* get the resolution from the light's size (we stuff it in there) */ - int res = background_light->map_resolution; - kintegrator->pdf_background_res = res; - - assert(res > 0); + int2 res = make_int2(background_light->map_resolution, background_light->map_resolution/2); + /* If the resolution isn't set manually, try to find an environment texture. */ + if (res.x == 0) { + Shader *shader = (scene->background->shader) ? scene->background->shader : scene->default_background; + foreach(ShaderNode *node, shader->graph->nodes) { + if(node->type == EnvironmentTextureNode::node_type) { + EnvironmentTextureNode *env = (EnvironmentTextureNode*) node; + ImageMetaData metadata; + if(env->image_manager && env->image_manager->get_image_metadata(env->slot, metadata)) { + res.x = max(res.x, metadata.width); + res.y = max(res.y, metadata.height); + } + } + } + if (res.x > 0 && res.y > 0) { + VLOG(2) << "Automatically set World MIS resolution to " << res.x << " by " << res.y << "\n"; + } + } + /* If it's still unknown, just use the default. */ + if (res.x == 0 || res.y == 0) { + res = make_int2(1024, 512); + VLOG(2) << "Setting World MIS resolution to default\n"; + } + kintegrator->pdf_background_res_x = res.x; + kintegrator->pdf_background_res_y = res.y; vector<float3> pixels; - shade_background_pixels(device, dscene, res, pixels, progress); + shade_background_pixels(device, dscene, res.x, res.y, pixels, progress); if(progress.get_cancel()) return; /* build row distributions and column distribution for the infinite area environment light */ - int cdf_count = res + 1; - float2 *marg_cdf = dscene->light_background_marginal_cdf.alloc(cdf_count); - float2 *cond_cdf = dscene->light_background_conditional_cdf.alloc(cdf_count * cdf_count); + int cdf_width = res.x+1; + float2 *marg_cdf = dscene->light_background_marginal_cdf.alloc(res.y + 1); + float2 *cond_cdf = dscene->light_background_conditional_cdf.alloc(cdf_width * res.y); double time_start = time_dt(); - if(res < 512) { + if(max(res.x, res.y) < 512) { /* Small enough resolution, faster to do single-threaded. */ - background_cdf(0, res, res, cdf_count, &pixels, cond_cdf); + background_cdf(0, res.x, res.x, res.y, &pixels, cond_cdf); } else { /* Threaded evaluation for large resolution. */ const int num_blocks = TaskScheduler::num_threads(); - const int chunk_size = res / num_blocks; + const int chunk_size = res.y / num_blocks; int start_row = 0; TaskPool pool; for(int i = 0; i < num_blocks; ++i) { const int current_chunk_size = (i != num_blocks - 1) ? chunk_size - : (res - i * chunk_size); + : (res.y - i * chunk_size); pool.push(function_bind(&background_cdf, start_row, start_row + current_chunk_size, - res, - cdf_count, + res.x, + res.y, &pixels, cond_cdf)); start_row += current_chunk_size; @@ -589,22 +611,22 @@ void LightManager::device_update_background(Device *device, } /* marginal CDFs (column, V direction, sum of rows) */ - marg_cdf[0].x = cond_cdf[res].x; + marg_cdf[0].x = cond_cdf[res.x].x; marg_cdf[0].y = 0.0f; - for(int i = 1; i < res; i++) { - marg_cdf[i].x = cond_cdf[i * cdf_count + res].x; - marg_cdf[i].y = marg_cdf[i - 1].y + marg_cdf[i - 1].x / res; + for(int i = 1; i < res.y; i++) { + marg_cdf[i].x = cond_cdf[i * cdf_width + res.x].x; + marg_cdf[i].y = marg_cdf[i - 1].y + marg_cdf[i - 1].x / res.y; } - float cdf_total = marg_cdf[res - 1].y + marg_cdf[res - 1].x / res; - marg_cdf[res].x = cdf_total; + float cdf_total = marg_cdf[res.y - 1].y + marg_cdf[res.y - 1].x / res.y; + marg_cdf[res.y].x = cdf_total; if(cdf_total > 0.0f) - for(int i = 1; i < res; i++) + for(int i = 1; i < res.y; i++) marg_cdf[i].y /= cdf_total; - marg_cdf[res].y = 1.0f; + marg_cdf[res.y].y = 1.0f; VLOG(2) << "Background MIS build time " << time_dt() - time_start << "\n"; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 3a531f87c10..1ddc84848cc 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "render/film.h" #include "render/image.h" #include "render/integrator.h" #include "render/light.h" @@ -1670,7 +1671,8 @@ RGBToBWNode::RGBToBWNode() 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); } } @@ -1766,7 +1768,8 @@ void ConvertNode::constant_fold(const ConstantFolder& folder) 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 */ diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index c1621cd817b..f8bd14859f2 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -31,6 +31,11 @@ #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; @@ -339,6 +344,40 @@ ShaderManager::ShaderManager() { 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() @@ -519,6 +558,14 @@ void ShaderManager::device_update_common(Device *device, 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) @@ -644,5 +691,10 @@ void ShaderManager::free_memory() beckmann_table.free_memory(); } +float ShaderManager::linear_rgb_to_gray(float3 c) +{ + return dot(c, rgb_to_y); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index ffaef522124..d787c3b266b 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -196,6 +196,8 @@ public: static void free_memory(); + float linear_rgb_to_gray(float3 c); + protected: ShaderManager(); @@ -212,6 +214,11 @@ protected: 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 diff --git a/intern/cycles/test/CMakeLists.txt b/intern/cycles/test/CMakeLists.txt index f3e49dc0c4e..46c525eb3bb 100644 --- a/intern/cycles/test/CMakeLists.txt +++ b/intern/cycles/test/CMakeLists.txt @@ -42,6 +42,11 @@ if(WITH_CYCLES_OSL) ${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}) diff --git a/intern/cycles/util/util_color.h b/intern/cycles/util/util_color.h index c73beab98dc..62a9bf8e47d 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,13 +150,6 @@ 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) -{ - 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 @@ -204,7 +197,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)); @@ -214,42 +207,37 @@ ccl_device ssef color_srgb_to_scene_linear(const ssef &c) } #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__ */ |