From eacdcb2dd80e9e2340fa7a4b8509448b0c72b77a Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Wed, 17 Jun 2020 20:27:10 +0200 Subject: Cycles: Add new Sky Texture method including direct sunlight This commit adds a new model to the Sky Texture node, which is based on a method by Nishita et al. and works by basically simulating volumetric scattering in the atmosphere. By making some approximations (such as only considering single scattering), we get a fairly simple and fast simulation code that takes into account Rayleigh and Mie scattering as well as Ozone absorption. This code is used to precompute a 512x128 texture which is then looked up during render time, and is fast enough to allow real-time tweaking in the viewport. Due to the nature of the simulation, it exposes several parameters that allow for lots of flexibility in choosing the look and matching real-world conditions (such as Air/Dust/Ozone density and altitude). Additionally, the same volumetric approach can be used to compute absorption of the direct sunlight, so the model also supports adding direct sunlight. This makes it significantly easier to set up Sun+Sky illumination where the direction, intensity and color of the sun actually matches the sky. In order to support properly sampling the direct sun component, the commit also adds logic for sampling a specific area to the kernel light sampling code. This is combined with portal and background map sampling using MIS. This sampling logic works for the common case of having one Sky texture going into the Background shader, but if a custom input to the Vector node is used or if there are multiple Sky textures, it falls back to using only background map sampling (while automatically setting the resolution to 4096x2048 if auto resolution is used). More infos and preview can be found here: https://docs.google.com/document/d/1gQta0ygFWXTrl5Pmvl_nZRgUw0mWg0FJeRuNKS36m08/view Underlying model, implementation and documentation by Marco (@nacioss). Improvements, cleanup and sun sampling by @lukasstockner. Differential Revision: https://developer.blender.org/D7896 --- intern/cycles/render/CMakeLists.txt | 2 + intern/cycles/render/image_sky.cpp | 95 +++++++++++++++++ intern/cycles/render/image_sky.h | 49 +++++++++ intern/cycles/render/light.cpp | 109 +++++++++++++++----- intern/cycles/render/nodes.cpp | 199 +++++++++++++++++++++++++++--------- intern/cycles/render/nodes.h | 9 ++ 6 files changed, 387 insertions(+), 76 deletions(-) create mode 100644 intern/cycles/render/image_sky.cpp create mode 100644 intern/cycles/render/image_sky.h (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index 472b5a0c101..e37a0407976 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -24,6 +24,7 @@ set(SRC hair.cpp image.cpp image_oiio.cpp + image_sky.cpp image_vdb.cpp integrator.cpp jitter.cpp @@ -64,6 +65,7 @@ set(SRC_HEADERS hair.h image.h image_oiio.h + image_sky.h image_vdb.h integrator.h light.h diff --git a/intern/cycles/render/image_sky.cpp b/intern/cycles/render/image_sky.cpp new file mode 100644 index 00000000000..3e7b491f609 --- /dev/null +++ b/intern/cycles/render/image_sky.cpp @@ -0,0 +1,95 @@ +/* + * Copyright 2011-2020 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. + */ + +#include "render/image_sky.h" + +#include "util/util_image.h" +#include "util/util_logging.h" +#include "util/util_path.h" +#include "util/util_sky_model.h" + +CCL_NAMESPACE_BEGIN + +SkyLoader::SkyLoader( + float sun_elevation, int altitude, float air_density, float dust_density, float ozone_density) + : sun_elevation(sun_elevation), + altitude(altitude), + air_density(air_density), + dust_density(dust_density), + ozone_density(ozone_density) +{ +} + +SkyLoader::~SkyLoader(){}; + +bool SkyLoader::load_metadata(ImageMetaData &metadata) +{ + metadata.width = 512; + metadata.height = 128; + metadata.channels = 3; + metadata.depth = 1; + metadata.type = IMAGE_DATA_TYPE_FLOAT4; + metadata.compress_as_srgb = false; + return true; +} + +bool SkyLoader::load_pixels(const ImageMetaData &metadata, + void *pixels, + const size_t /*pixels_size*/, + const bool /*associate_alpha*/) +{ + /* definitions */ + int width = metadata.width; + int height = metadata.height; + float *pixel_data = (float *)pixels; + float altitude_f = (float)altitude; + + /* precompute sky texture */ + const int num_chunks = TaskScheduler::num_threads(); + const int chunk_size = height / num_chunks; + TaskPool pool; + for (int chunk = 0; chunk < num_chunks; chunk++) { + const int chunk_start = chunk * chunk_size; + const int chunk_end = (chunk + 1 < num_chunks) ? (chunk + 1) * chunk_size : height; + pool.push(function_bind(&nishita_skymodel_precompute_texture, + pixel_data, + metadata.channels, + chunk_start, + chunk_end, + width, + height, + sun_elevation, + altitude_f, + air_density, + dust_density, + ozone_density)); + } + pool.wait_work(); + + return true; +} + +string SkyLoader::name() const +{ + return "sky_nishita"; +} + +bool SkyLoader::equals(const ImageLoader & /*other*/) const +{ + return false; +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/image_sky.h b/intern/cycles/render/image_sky.h new file mode 100644 index 00000000000..cf4a3e8942c --- /dev/null +++ b/intern/cycles/render/image_sky.h @@ -0,0 +1,49 @@ +/* + * Copyright 2011-2020 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. + */ + +#include "render/image.h" + +CCL_NAMESPACE_BEGIN + +class SkyLoader : public ImageLoader { + private: + float sun_elevation; + int altitude; + float air_density; + float dust_density; + float ozone_density; + + public: + SkyLoader(float sun_elevation, + int altitude, + float air_density, + float dust_density, + float ozone_density); + ~SkyLoader(); + + bool load_metadata(ImageMetaData &metadata) override; + + bool load_pixels(const ImageMetaData &metadata, + void *pixels, + const size_t /*pixels_size*/, + const bool /*associate_alpha*/) override; + + string name() const override; + + bool equals(const ImageLoader & /*other*/) const override; +}; + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index cb7474017fa..225cedfef55 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -450,6 +450,7 @@ void LightManager::device_update_distribution(Device *, /* update device */ KernelIntegrator *kintegrator = &dscene->data.integrator; + KernelBackground *kbackground = &dscene->data.background; KernelFilm *kfilm = &dscene->data.film; kintegrator->use_direct_light = (totarea > 0.0f); @@ -493,15 +494,18 @@ void LightManager::device_update_distribution(Device *, /* Portals */ if (num_portals > 0) { - kintegrator->portal_offset = light_index; - kintegrator->num_portals = num_portals; - kintegrator->portal_pdf = background_mis ? 0.5f : 1.0f; + kbackground->portal_offset = light_index; + kbackground->num_portals = num_portals; + kbackground->portal_weight = 1.0f; } else { - kintegrator->num_portals = 0; - kintegrator->portal_offset = 0; - kintegrator->portal_pdf = 0.0f; + kbackground->num_portals = 0; + kbackground->portal_offset = 0; + kbackground->portal_weight = 0.0f; } + + /* Map */ + kbackground->map_weight = background_mis ? 1.0f : 0.0f; } else { dscene->light_distribution.free(); @@ -511,9 +515,12 @@ void LightManager::device_update_distribution(Device *, kintegrator->pdf_triangles = 0.0f; kintegrator->pdf_lights = 0.0f; kintegrator->use_lamp_mis = false; - kintegrator->num_portals = 0; - kintegrator->portal_offset = 0; - kintegrator->portal_pdf = 0.0f; + + kbackground->num_portals = 0; + kbackground->portal_offset = 0; + kbackground->portal_weight = 0.0f; + kbackground->sun_weight = 0.0f; + kbackground->map_weight = 0.0f; kfilm->pass_shadow_scale = 1.0f; } @@ -562,7 +569,7 @@ void LightManager::device_update_background(Device *device, Scene *scene, Progress &progress) { - KernelIntegrator *kintegrator = &dscene->data.integrator; + KernelBackground *kbackground = &dscene->data.background; Light *background_light = NULL; /* find background light */ @@ -575,31 +582,79 @@ 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_x = 0; - kintegrator->pdf_background_res_y = 0; + kbackground->map_res_x = 0; + kbackground->map_res_y = 0; + kbackground->map_weight = 0.0f; + kbackground->sun_weight = 0.0f; + kbackground->use_mis = (kbackground->portal_weight > 0.0f); return; } progress.set_status("Updating Lights", "Importance map"); - assert(kintegrator->use_direct_light); + assert(dscene->data.integrator.use_direct_light); + + int2 environment_res = make_int2(0, 0); + Shader *shader = scene->background->get_shader(scene); + int num_suns = 0; + foreach (ShaderNode *node, shader->graph->nodes) { + if (node->type == EnvironmentTextureNode::node_type) { + EnvironmentTextureNode *env = (EnvironmentTextureNode *)node; + ImageMetaData metadata; + if (!env->handle.empty()) { + ImageMetaData metadata = env->handle.metadata(); + environment_res.x = max(environment_res.x, metadata.width); + environment_res.y = max(environment_res.y, metadata.height); + } + } + if (node->type == SkyTextureNode::node_type) { + SkyTextureNode *sky = (SkyTextureNode *)node; + if (sky->type == NODE_SKY_NISHITA && sky->sun_disc) { + /* Ensure that the input coordinates aren't transformed before they reach the node. + * If that is the case, the logic used for sampling the sun's location does not work + * and we have to fall back to map-based sampling. */ + const ShaderInput *vec_in = sky->input("Vector"); + if (vec_in && vec_in->link && vec_in->link->parent) { + ShaderNode *vec_src = vec_in->link->parent; + if ((vec_src->type != TextureCoordinateNode::node_type) || + (vec_in->link != vec_src->output("Generated"))) { + environment_res.x = max(environment_res.x, 4096); + environment_res.y = max(environment_res.y, 2048); + continue; + } + } + + float latitude = sky->sun_elevation; + float longitude = M_2PI_F - sky->sun_rotation + M_PI_2_F; + float half_angle = sky->sun_size * 0.5f; + kbackground->sun = make_float4(cosf(latitude) * cosf(longitude), + cosf(latitude) * sinf(longitude), + sinf(latitude), + half_angle); + kbackground->sun_weight = 4.0f; + environment_res.x = max(environment_res.x, 512); + environment_res.y = max(environment_res.y, 256); + num_suns++; + } + } + } + + /* If there's more than one sun, fall back to map sampling instead. */ + if (num_suns != 1) { + kbackground->sun_weight = 0.0f; + environment_res.x = max(environment_res.x, 4096); + environment_res.y = max(environment_res.y, 2048); + } + + /* Enable MIS for background sampling if any strategy is active. */ + kbackground->use_mis = (kbackground->portal_weight + kbackground->map_weight + + kbackground->sun_weight) > 0.0f; /* get the resolution from the light's size (we stuff it in there) */ 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->get_shader(scene); - foreach (ShaderNode *node, shader->graph->nodes) { - if (node->type == EnvironmentTextureNode::node_type) { - EnvironmentTextureNode *env = (EnvironmentTextureNode *)node; - ImageMetaData metadata; - if (!env->handle.empty()) { - ImageMetaData metadata = env->handle.metadata(); - res.x = max(res.x, metadata.width); - res.y = max(res.y, metadata.height); - } - } - } + res = environment_res; if (res.x > 0 && res.y > 0) { VLOG(2) << "Automatically set World MIS resolution to " << res.x << " by " << res.y << "\n"; } @@ -609,8 +664,8 @@ void LightManager::device_update_background(Device *device, 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; + kbackground->map_res_x = res.x; + kbackground->map_res_y = res.y; vector pixels; shade_background_pixels(device, dscene, res.x, res.y, pixels, progress); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index cdcaeb246dd..ab392839e52 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -19,6 +19,7 @@ #include "render/constant_fold.h" #include "render/film.h" #include "render/image.h" +#include "render/image_sky.h" #include "render/integrator.h" #include "render/light.h" #include "render/mesh.h" @@ -630,7 +631,7 @@ typedef struct SunSky { /* Parameter */ float radiance_x, radiance_y, radiance_z; - float config_x[9], config_y[9], config_z[9]; + float config_x[9], config_y[9], config_z[9], nishita_data[9]; } SunSky; /* Preetham model */ @@ -640,7 +641,7 @@ static float sky_perez_function(float lam[6], float theta, float gamma) (1.0f + lam[2] * expf(lam[3] * gamma) + lam[4] * cosf(gamma) * cosf(gamma)); } -static void sky_texture_precompute_old(SunSky *sunsky, float3 dir, float turbidity) +static void sky_texture_precompute_preetham(SunSky *sunsky, float3 dir, float turbidity) { /* * We re-use the SunSky struct of the new model, to avoid extra variables @@ -703,10 +704,10 @@ static void sky_texture_precompute_old(SunSky *sunsky, float3 dir, float turbidi } /* Hosek / Wilkie */ -static void sky_texture_precompute_new(SunSky *sunsky, - float3 dir, - float turbidity, - float ground_albedo) +static void sky_texture_precompute_hosek(SunSky *sunsky, + float3 dir, + float turbidity, + float ground_albedo) { /* Calculate Sun Direction and save coordinates */ float2 spherical = sky_spherical_coordinates(dir); @@ -743,6 +744,34 @@ static void sky_texture_precompute_new(SunSky *sunsky, arhosekskymodelstate_free(sky_state); } +/* Nishita improved */ +static void sky_texture_precompute_nishita(SunSky *sunsky, + bool sun_disc, + float sun_size, + float sun_elevation, + float sun_rotation, + int altitude, + float air_density, + float dust_density) +{ + /* sample 2 sun pixels */ + float pixel_bottom[3]; + float pixel_top[3]; + float altitude_f = (float)altitude; + nishita_skymodel_precompute_sun( + sun_elevation, sun_size, altitude_f, air_density, dust_density, pixel_bottom, pixel_top); + /* send data to svm_sky */ + sunsky->nishita_data[0] = pixel_bottom[0]; + sunsky->nishita_data[1] = pixel_bottom[1]; + sunsky->nishita_data[2] = pixel_bottom[2]; + sunsky->nishita_data[3] = pixel_top[0]; + sunsky->nishita_data[4] = pixel_top[1]; + sunsky->nishita_data[5] = pixel_top[2]; + sunsky->nishita_data[6] = sun_elevation; + sunsky->nishita_data[7] = M_2PI_F - sun_rotation; + sunsky->nishita_data[8] = sun_disc ? sun_size : 0.0f; +} + NODE_DEFINE(SkyTextureNode) { NodeType *type = NodeType::add("sky_texture", create, NodeType::SHADER); @@ -750,13 +779,22 @@ NODE_DEFINE(SkyTextureNode) TEXTURE_MAPPING_DEFINE(SkyTextureNode); static NodeEnum type_enum; - type_enum.insert("preetham", NODE_SKY_OLD); - type_enum.insert("hosek_wilkie", NODE_SKY_NEW); - SOCKET_ENUM(type, "Type", type_enum, NODE_SKY_NEW); + type_enum.insert("preetham", NODE_SKY_PREETHAM); + type_enum.insert("hosek_wilkie", NODE_SKY_HOSEK); + type_enum.insert("nishita_improved", NODE_SKY_NISHITA); + SOCKET_ENUM(type, "Type", type_enum, NODE_SKY_NISHITA); SOCKET_VECTOR(sun_direction, "Sun Direction", make_float3(0.0f, 0.0f, 1.0f)); SOCKET_FLOAT(turbidity, "Turbidity", 2.2f); SOCKET_FLOAT(ground_albedo, "Ground Albedo", 0.3f); + SOCKET_BOOLEAN(sun_disc, "Sun Disc", true); + SOCKET_FLOAT(sun_size, "Sun Size", 0.009512f); + SOCKET_FLOAT(sun_elevation, "Sun Elevation", M_PI_2_F); + SOCKET_FLOAT(sun_rotation, "Sun Rotation", 0.0f); + SOCKET_INT(altitude, "Altitude", 0); + SOCKET_FLOAT(air_density, "Air", 1.0f); + SOCKET_FLOAT(dust_density, "Dust", 1.0f); + SOCKET_FLOAT(ozone_density, "Ozone", 1.0f); SOCKET_IN_POINT( vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED); @@ -776,10 +814,32 @@ void SkyTextureNode::compile(SVMCompiler &compiler) ShaderOutput *color_out = output("Color"); SunSky sunsky; - if (type == NODE_SKY_OLD) - sky_texture_precompute_old(&sunsky, sun_direction, turbidity); - else if (type == NODE_SKY_NEW) - sky_texture_precompute_new(&sunsky, sun_direction, turbidity, ground_albedo); + if (type == NODE_SKY_PREETHAM) + sky_texture_precompute_preetham(&sunsky, sun_direction, turbidity); + else if (type == NODE_SKY_HOSEK) + sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo); + else if (type == NODE_SKY_NISHITA) { + sky_texture_precompute_nishita(&sunsky, + sun_disc, + sun_size, + sun_elevation, + sun_rotation, + altitude, + air_density, + dust_density); + /* precomputed texture image parameters */ + ImageManager *image_manager = compiler.scene->image_manager; + ImageParams impar; + impar.interpolation = INTERPOLATION_LINEAR; + impar.extension = EXTENSION_EXTEND; + + /* precompute sky texture */ + if (handle.empty()) { + SkyLoader *loader = new SkyLoader( + sun_elevation, altitude, air_density, dust_density, ozone_density); + handle = image_manager->add_image(loader, impar); + } + } else assert(false); @@ -787,38 +847,52 @@ void SkyTextureNode::compile(SVMCompiler &compiler) compiler.stack_assign(color_out); compiler.add_node(NODE_TEX_SKY, vector_offset, compiler.stack_assign(color_out), type); - compiler.add_node(__float_as_uint(sunsky.phi), - __float_as_uint(sunsky.theta), - __float_as_uint(sunsky.radiance_x), - __float_as_uint(sunsky.radiance_y)); - compiler.add_node(__float_as_uint(sunsky.radiance_z), - __float_as_uint(sunsky.config_x[0]), - __float_as_uint(sunsky.config_x[1]), - __float_as_uint(sunsky.config_x[2])); - compiler.add_node(__float_as_uint(sunsky.config_x[3]), - __float_as_uint(sunsky.config_x[4]), - __float_as_uint(sunsky.config_x[5]), - __float_as_uint(sunsky.config_x[6])); - compiler.add_node(__float_as_uint(sunsky.config_x[7]), - __float_as_uint(sunsky.config_x[8]), - __float_as_uint(sunsky.config_y[0]), - __float_as_uint(sunsky.config_y[1])); - compiler.add_node(__float_as_uint(sunsky.config_y[2]), - __float_as_uint(sunsky.config_y[3]), - __float_as_uint(sunsky.config_y[4]), - __float_as_uint(sunsky.config_y[5])); - compiler.add_node(__float_as_uint(sunsky.config_y[6]), - __float_as_uint(sunsky.config_y[7]), - __float_as_uint(sunsky.config_y[8]), - __float_as_uint(sunsky.config_z[0])); - compiler.add_node(__float_as_uint(sunsky.config_z[1]), - __float_as_uint(sunsky.config_z[2]), - __float_as_uint(sunsky.config_z[3]), - __float_as_uint(sunsky.config_z[4])); - compiler.add_node(__float_as_uint(sunsky.config_z[5]), - __float_as_uint(sunsky.config_z[6]), - __float_as_uint(sunsky.config_z[7]), - __float_as_uint(sunsky.config_z[8])); + /* nishita doesn't need this data */ + if (type != NODE_SKY_NISHITA) { + compiler.add_node(__float_as_uint(sunsky.phi), + __float_as_uint(sunsky.theta), + __float_as_uint(sunsky.radiance_x), + __float_as_uint(sunsky.radiance_y)); + compiler.add_node(__float_as_uint(sunsky.radiance_z), + __float_as_uint(sunsky.config_x[0]), + __float_as_uint(sunsky.config_x[1]), + __float_as_uint(sunsky.config_x[2])); + compiler.add_node(__float_as_uint(sunsky.config_x[3]), + __float_as_uint(sunsky.config_x[4]), + __float_as_uint(sunsky.config_x[5]), + __float_as_uint(sunsky.config_x[6])); + compiler.add_node(__float_as_uint(sunsky.config_x[7]), + __float_as_uint(sunsky.config_x[8]), + __float_as_uint(sunsky.config_y[0]), + __float_as_uint(sunsky.config_y[1])); + compiler.add_node(__float_as_uint(sunsky.config_y[2]), + __float_as_uint(sunsky.config_y[3]), + __float_as_uint(sunsky.config_y[4]), + __float_as_uint(sunsky.config_y[5])); + compiler.add_node(__float_as_uint(sunsky.config_y[6]), + __float_as_uint(sunsky.config_y[7]), + __float_as_uint(sunsky.config_y[8]), + __float_as_uint(sunsky.config_z[0])); + compiler.add_node(__float_as_uint(sunsky.config_z[1]), + __float_as_uint(sunsky.config_z[2]), + __float_as_uint(sunsky.config_z[3]), + __float_as_uint(sunsky.config_z[4])); + compiler.add_node(__float_as_uint(sunsky.config_z[5]), + __float_as_uint(sunsky.config_z[6]), + __float_as_uint(sunsky.config_z[7]), + __float_as_uint(sunsky.config_z[8])); + } + else { + compiler.add_node(__float_as_uint(sunsky.nishita_data[0]), + __float_as_uint(sunsky.nishita_data[1]), + __float_as_uint(sunsky.nishita_data[2]), + __float_as_uint(sunsky.nishita_data[3])); + compiler.add_node(__float_as_uint(sunsky.nishita_data[4]), + __float_as_uint(sunsky.nishita_data[5]), + __float_as_uint(sunsky.nishita_data[6]), + __float_as_uint(sunsky.nishita_data[7])); + compiler.add_node(__float_as_uint(sunsky.nishita_data[8]), handle.svm_slot(), 0, 0); + } tex_mapping.compile_end(compiler, vector_in, vector_offset); } @@ -828,10 +902,32 @@ void SkyTextureNode::compile(OSLCompiler &compiler) tex_mapping.compile(compiler); SunSky sunsky; - if (type == NODE_SKY_OLD) - sky_texture_precompute_old(&sunsky, sun_direction, turbidity); - else if (type == NODE_SKY_NEW) - sky_texture_precompute_new(&sunsky, sun_direction, turbidity, ground_albedo); + if (type == NODE_SKY_PREETHAM) + sky_texture_precompute_preetham(&sunsky, sun_direction, turbidity); + else if (type == NODE_SKY_HOSEK) + sky_texture_precompute_hosek(&sunsky, sun_direction, turbidity, ground_albedo); + else if (type == NODE_SKY_NISHITA) { + sky_texture_precompute_nishita(&sunsky, + sun_disc, + sun_size, + sun_elevation, + sun_rotation, + altitude, + air_density, + dust_density); + /* precomputed texture image parameters */ + ImageManager *image_manager = compiler.scene->image_manager; + ImageParams impar; + impar.interpolation = INTERPOLATION_LINEAR; + impar.extension = EXTENSION_EXTEND; + + /* precompute sky texture */ + if (handle.empty()) { + SkyLoader *loader = new SkyLoader( + sun_elevation, altitude, air_density, dust_density, ozone_density); + handle = image_manager->add_image(loader, impar); + } + } else assert(false); @@ -843,6 +939,11 @@ void SkyTextureNode::compile(OSLCompiler &compiler) compiler.parameter_array("config_x", sunsky.config_x, 9); compiler.parameter_array("config_y", sunsky.config_y, 9); compiler.parameter_array("config_z", sunsky.config_z, 9); + compiler.parameter_array("nishita_data", sunsky.nishita_data, 9); + /* nishita texture */ + if (type == NODE_SKY_NISHITA) { + compiler.parameter_texture("filename", handle.svm_slot()); + } compiler.add(this, "node_sky_texture"); } diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 83c3ad071ae..846ba7423e5 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -168,7 +168,16 @@ class SkyTextureNode : public TextureNode { float3 sun_direction; float turbidity; float ground_albedo; + bool sun_disc; + float sun_size; + float sun_elevation; + float sun_rotation; + int altitude; + float air_density; + float dust_density; + float ozone_density; float3 vector; + ImageHandle handle; }; class OutputNode : public ShaderNode { -- cgit v1.2.3 From ace3268482c6bfd9986815aaa6b027c99fa8e3f4 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 5 Jun 2020 11:39:11 +0200 Subject: Cleanup: minor refactoring around DeviceTask --- intern/cycles/render/denoising.cpp | 1 + intern/cycles/render/geometry.cpp | 5 ++--- intern/cycles/render/image.cpp | 1 + intern/cycles/render/image.h | 2 +- intern/cycles/render/integrator.cpp | 1 + intern/cycles/render/light.cpp | 1 + intern/cycles/render/object.cpp | 1 + intern/cycles/render/shader.cpp | 1 + 8 files changed, 9 insertions(+), 4 deletions(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/denoising.cpp b/intern/cycles/render/denoising.cpp index 4d819d1119e..93815ebfbc4 100644 --- a/intern/cycles/render/denoising.cpp +++ b/intern/cycles/render/denoising.cpp @@ -21,6 +21,7 @@ #include "util/util_foreach.h" #include "util/util_map.h" #include "util/util_system.h" +#include "util/util_task.h" #include "util/util_time.h" #include diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp index d46ed430c4f..f448c2fb07f 100644 --- a/intern/cycles/render/geometry.cpp +++ b/intern/cycles/render/geometry.cpp @@ -16,10 +16,9 @@ #include "bvh/bvh.h" #include "bvh/bvh_build.h" +#include "bvh/bvh_embree.h" -#ifdef WITH_EMBREE -# include "bvh/bvh_embree.h" -#endif +#include "device/device.h" #include "render/attribute.h" #include "render/camera.h" diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 75050b66bf2..8d187814d64 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -27,6 +27,7 @@ #include "util/util_logging.h" #include "util/util_path.h" #include "util/util_progress.h" +#include "util/util_task.h" #include "util/util_texture.h" #include "util/util_unique_ptr.h" diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 2000582ce70..fffe7c5152a 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -17,7 +17,6 @@ #ifndef __IMAGE_H__ #define __IMAGE_H__ -#include "device/device.h" #include "device/device_memory.h" #include "render/colorspace.h" @@ -31,6 +30,7 @@ CCL_NAMESPACE_BEGIN class Device; +class DeviceInfo; class ImageHandle; class ImageKey; class ImageMetaData; diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index d4beb06e57b..eff416efa2b 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -29,6 +29,7 @@ #include "util/util_foreach.h" #include "util/util_hash.h" #include "util/util_logging.h" +#include "util/util_task.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 225cedfef55..25c91a76d58 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -31,6 +31,7 @@ #include "util/util_logging.h" #include "util/util_path.h" #include "util/util_progress.h" +#include "util/util_task.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 61deef4cd76..752350ad76e 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -31,6 +31,7 @@ #include "util/util_murmurhash.h" #include "util/util_progress.h" #include "util/util_set.h" +#include "util/util_task.h" #include "util/util_vector.h" #include "subd/subd_patch_table.h" diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 39ba45a751a..1120d909e98 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -33,6 +33,7 @@ #include "util/util_foreach.h" #include "util/util_murmurhash.h" +#include "util/util_task.h" #ifdef WITH_OCIO # include -- cgit v1.2.3 From d8c2092b15de61a69bddbc082998a1dc786d73af Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 5 Jun 2020 12:53:38 +0200 Subject: Cycles: make TBB a required library dependency, and use in a few places Now that the rest of Blender also relies on TBB, no point in maintaining custom code for paraller_for and thread local storage. --- intern/cycles/render/image_sky.cpp | 36 +++++++++----------- intern/cycles/render/light.cpp | 30 ++++------------- intern/cycles/render/object.cpp | 69 ++++++-------------------------------- intern/cycles/render/svm.cpp | 3 +- 4 files changed, 34 insertions(+), 104 deletions(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/image_sky.cpp b/intern/cycles/render/image_sky.cpp index 3e7b491f609..442e1d7941f 100644 --- a/intern/cycles/render/image_sky.cpp +++ b/intern/cycles/render/image_sky.cpp @@ -20,6 +20,7 @@ #include "util/util_logging.h" #include "util/util_path.h" #include "util/util_sky_model.h" +#include "util/util_task.h" CCL_NAMESPACE_BEGIN @@ -58,26 +59,21 @@ bool SkyLoader::load_pixels(const ImageMetaData &metadata, float altitude_f = (float)altitude; /* precompute sky texture */ - const int num_chunks = TaskScheduler::num_threads(); - const int chunk_size = height / num_chunks; - TaskPool pool; - for (int chunk = 0; chunk < num_chunks; chunk++) { - const int chunk_start = chunk * chunk_size; - const int chunk_end = (chunk + 1 < num_chunks) ? (chunk + 1) * chunk_size : height; - pool.push(function_bind(&nishita_skymodel_precompute_texture, - pixel_data, - metadata.channels, - chunk_start, - chunk_end, - width, - height, - sun_elevation, - altitude_f, - air_density, - dust_density, - ozone_density)); - } - pool.wait_work(); + const int rows_per_task = divide_up(1024, width); + parallel_for(blocked_range(0, height, rows_per_task), + [&](const blocked_range &r) { + nishita_skymodel_precompute_texture(pixel_data, + metadata.channels, + r.begin(), + r.end(), + width, + height, + sun_elevation, + altitude_f, + air_density, + dust_density, + ozone_density); + }); return true; } diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 25c91a76d58..c0615c6217b 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -680,29 +680,13 @@ void LightManager::device_update_background(Device *device, float2 *cond_cdf = dscene->light_background_conditional_cdf.alloc(cdf_width * res.y); double time_start = time_dt(); - if (max(res.x, res.y) < 512) { - /* Small enough resolution, faster to do single-threaded. */ - background_cdf(0, res.y, 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.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.y - i * chunk_size); - pool.push(function_bind(&background_cdf, - start_row, - start_row + current_chunk_size, - res.x, - res.y, - &pixels, - cond_cdf)); - start_row += current_chunk_size; - } - pool.wait_work(); - } + + /* Create CDF in parallel. */ + const int rows_per_task = divide_up(10240, res.x); + parallel_for(blocked_range(0, res.y, rows_per_task), + [&](const blocked_range &r) { + background_cdf(r.begin(), r.end(), res.x, res.y, &pixels, cond_cdf); + }); /* marginal CDFs (column, V direction, sum of rows) */ marg_cdf[0].x = cond_cdf[res.x].x; diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 752350ad76e..28337ef1a21 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -78,7 +78,6 @@ struct UpdateObjectTransformState { Scene *scene; /* Some locks to keep everything thread-safe. */ - thread_spin_lock queue_lock; thread_spin_lock surface_area_lock; /* First unused object index in the queue. */ @@ -551,41 +550,6 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s } } -bool ObjectManager::device_update_object_transform_pop_work(UpdateObjectTransformState *state, - int *start_index, - int *num_objects) -{ - /* Tweakable parameter, number of objects per chunk. - * Too small value will cause some extra overhead due to spin lock, - * too big value might not use all threads nicely. - */ - static const int OBJECTS_PER_TASK = 32; - bool have_work = false; - state->queue_lock.lock(); - int num_scene_objects = state->scene->objects.size(); - if (state->queue_start_object < num_scene_objects) { - int count = min(OBJECTS_PER_TASK, num_scene_objects - state->queue_start_object); - *start_index = state->queue_start_object; - *num_objects = count; - state->queue_start_object += count; - have_work = true; - } - state->queue_lock.unlock(); - return have_work; -} - -void ObjectManager::device_update_object_transform_task(UpdateObjectTransformState *state) -{ - int start_index, num_objects; - while (device_update_object_transform_pop_work(state, &start_index, &num_objects)) { - for (int i = 0; i < num_objects; ++i) { - const int object_index = start_index + i; - Object *ob = state->scene->objects[object_index]; - device_update_object_transform(state, ob); - } - } -} - void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, Progress &progress) { UpdateObjectTransformState state; @@ -631,29 +595,16 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, numparticles += psys->particles.size(); } - /* NOTE: If it's just a handful of objects we deal with them in a single - * thread to avoid threading overhead. However, this threshold is might - * need some tweaks to make mid-complex scenes optimal. - */ - if (scene->objects.size() < 64) { - foreach (Object *ob, scene->objects) { - device_update_object_transform(&state, ob); - if (progress.get_cancel()) { - return; - } - } - } - else { - const int num_threads = TaskScheduler::num_threads(); - TaskPool pool; - for (int i = 0; i < num_threads; ++i) { - pool.push(function_bind(&ObjectManager::device_update_object_transform_task, this, &state)); - } - pool.wait_work(); - if (progress.get_cancel()) { - return; - } - } + /* Parallel object update, with grain size to avoid too much threadng overhead + * for individual objects. */ + static const int OBJECTS_PER_TASK = 32; + parallel_for(blocked_range(0, scene->objects.size(), OBJECTS_PER_TASK), + [&](const blocked_range &r) { + for (size_t i = r.begin(); i != r.end(); i++) { + Object *ob = state.scene->objects[i]; + device_update_object_transform(&state, ob); + } + }); dscene->objects.copy_to_device(); if (state.need_motion == Scene::MOTION_PASS) { diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index ea3dbaf8e03..88714e20a90 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -94,8 +94,7 @@ void SVMShaderManager::device_update(Device *device, scene, scene->shaders[i], &progress, - &shader_svm_nodes[i]), - false); + &shader_svm_nodes[i])); } task_pool.wait_work(); -- cgit v1.2.3 From c7d940278b16bb357a848f176d070e1784ccdde2 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 4 Jun 2020 15:12:31 +0200 Subject: Cycles: remove support for rendering hair as triangle and lines Triangles were very memory intensive. The only reason they were not removed yet is that they gave more accurate results, but there will be an accurate 3D curve primitive added for this. Line rendering was always poor quality since the ends do not match up. To keep CPU and GPU compatibility we just remove them entirely. They could be brought back if an Embree compatible implementation is added, but it's not clear to me that there is a use case for these that we'd consider important. Ref T73778 Reviewers: #cycles Subscribers: --- intern/cycles/render/curves.cpp | 41 ++++++++--------------------------------- intern/cycles/render/curves.h | 26 -------------------------- 2 files changed, 8 insertions(+), 59 deletions(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp index 1907bb33d06..a223702cfab 100644 --- a/intern/cycles/render/curves.cpp +++ b/intern/cycles/render/curves.cpp @@ -81,17 +81,11 @@ void curvebounds(float *lower, float *upper, float3 *p, int dim) CurveSystemManager::CurveSystemManager() { - primitive = CURVE_LINE_SEGMENTS; curve_shape = CURVE_THICK; - line_method = CURVE_CORRECTED; - triangle_method = CURVE_CAMERA_TRIANGLES; - resolution = 3; subdivisions = 3; use_curves = true; - use_encasing = true; use_backfacing = false; - use_tangent_normal_geometry = false; need_update = true; need_mesh_update = false; @@ -118,22 +112,12 @@ void CurveSystemManager::device_update(Device *device, kcurve->curveflags = 0; if (use_curves) { - if (primitive == CURVE_SEGMENTS || primitive == CURVE_RIBBONS) - kcurve->curveflags |= CURVE_KN_INTERPOLATE; - if (primitive == CURVE_RIBBONS) + if (curve_shape == CURVE_RIBBON) { kcurve->curveflags |= CURVE_KN_RIBBONS; - - if (line_method == CURVE_ACCURATE) - kcurve->curveflags |= CURVE_KN_ACCURATE; - else if (line_method == CURVE_CORRECTED) - kcurve->curveflags |= CURVE_KN_INTERSECTCORRECTION; - - if (use_tangent_normal_geometry) - kcurve->curveflags |= CURVE_KN_TRUETANGENTGNORMAL; - if (use_backfacing) + } + else if (use_backfacing) { kcurve->curveflags |= CURVE_KN_BACKFACING; - if (use_encasing) - kcurve->curveflags |= CURVE_KN_ENCLOSEFILTER; + } kcurve->subdivisions = subdivisions; } @@ -150,23 +134,14 @@ void CurveSystemManager::device_free(Device * /*device*/, DeviceScene * /*dscene bool CurveSystemManager::modified(const CurveSystemManager &CurveSystemManager) { - return !( - curve_shape == CurveSystemManager.curve_shape && - line_method == CurveSystemManager.line_method && primitive == CurveSystemManager.primitive && - use_encasing == CurveSystemManager.use_encasing && - use_tangent_normal_geometry == CurveSystemManager.use_tangent_normal_geometry && - use_backfacing == CurveSystemManager.use_backfacing && - triangle_method == CurveSystemManager.triangle_method && - resolution == CurveSystemManager.resolution && use_curves == CurveSystemManager.use_curves && - subdivisions == CurveSystemManager.subdivisions); + return !(use_backfacing == CurveSystemManager.use_backfacing && + use_curves == CurveSystemManager.use_curves && + subdivisions == CurveSystemManager.subdivisions); } bool CurveSystemManager::modified_mesh(const CurveSystemManager &CurveSystemManager) { - return !( - primitive == CurveSystemManager.primitive && curve_shape == CurveSystemManager.curve_shape && - triangle_method == CurveSystemManager.triangle_method && - resolution == CurveSystemManager.resolution && use_curves == CurveSystemManager.use_curves); + return !(use_curves == CurveSystemManager.use_curves); } void CurveSystemManager::tag_update(Scene * /*scene*/) diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h index ade289a402e..047db32b44b 100644 --- a/intern/cycles/render/curves.h +++ b/intern/cycles/render/curves.h @@ -29,15 +29,6 @@ class Scene; void curvebounds(float *lower, float *upper, float3 *p, int dim); -typedef enum CurvePrimitiveType { - CURVE_TRIANGLES = 0, - CURVE_LINE_SEGMENTS = 1, - CURVE_SEGMENTS = 2, - CURVE_RIBBONS = 3, - - CURVE_NUM_PRIMITIVE_TYPES, -} CurvePrimitiveType; - typedef enum CurveShapeType { CURVE_RIBBON = 0, CURVE_THICK = 1, @@ -45,17 +36,6 @@ typedef enum CurveShapeType { CURVE_NUM_SHAPE_TYPES, } CurveShapeType; -typedef enum CurveTriangleMethod { - CURVE_CAMERA_TRIANGLES, - CURVE_TESSELATED_TRIANGLES -} CurveTriangleMethod; - -typedef enum CurveLineMethod { - CURVE_ACCURATE, - CURVE_CORRECTED, - CURVE_UNCORRECTED -} CurveLineMethod; - class ParticleCurveData { public: @@ -85,17 +65,11 @@ class ParticleCurveData { class CurveSystemManager { public: - CurvePrimitiveType primitive; CurveShapeType curve_shape; - CurveLineMethod line_method; - CurveTriangleMethod triangle_method; - int resolution; int subdivisions; bool use_curves; - bool use_encasing; bool use_backfacing; - bool use_tangent_normal_geometry; bool need_update; bool need_mesh_update; -- cgit v1.2.3 From fed101a7be119f2e0c4ed64d13fd65f7a1c16118 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 10 Jun 2020 18:34:18 +0200 Subject: Cycles: always perform backface culling for curve, remove option The hair BSDFs are already designed to assume this, and disabling backface culling would break them in some cases. Ref T73778 Depends on D8009 Maniphest Tasks: T73778 Differential Revision: https://developer.blender.org/D8010 --- intern/cycles/render/curves.cpp | 7 +------ intern/cycles/render/curves.h | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp index a223702cfab..0d2be71eed8 100644 --- a/intern/cycles/render/curves.cpp +++ b/intern/cycles/render/curves.cpp @@ -85,7 +85,6 @@ CurveSystemManager::CurveSystemManager() subdivisions = 3; use_curves = true; - use_backfacing = false; need_update = true; need_mesh_update = false; @@ -115,9 +114,6 @@ void CurveSystemManager::device_update(Device *device, if (curve_shape == CURVE_RIBBON) { kcurve->curveflags |= CURVE_KN_RIBBONS; } - else if (use_backfacing) { - kcurve->curveflags |= CURVE_KN_BACKFACING; - } kcurve->subdivisions = subdivisions; } @@ -134,8 +130,7 @@ void CurveSystemManager::device_free(Device * /*device*/, DeviceScene * /*dscene bool CurveSystemManager::modified(const CurveSystemManager &CurveSystemManager) { - return !(use_backfacing == CurveSystemManager.use_backfacing && - use_curves == CurveSystemManager.use_curves && + return !(use_curves == CurveSystemManager.use_curves && subdivisions == CurveSystemManager.subdivisions); } diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h index 047db32b44b..e6b0a3b4706 100644 --- a/intern/cycles/render/curves.h +++ b/intern/cycles/render/curves.h @@ -69,7 +69,6 @@ class CurveSystemManager { int subdivisions; bool use_curves; - bool use_backfacing; bool need_update; bool need_mesh_update; -- cgit v1.2.3 From 1de0e13af619e405f351bf42924f819dc3a9bc44 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 23 Feb 2020 10:15:35 +0100 Subject: Cycles: remove __UV__ and __INSTANCING__ as kernel options The kernel did not work correctly when these were disabled anyway. The optimized BVH traversal for the no instances case was also only used on the CPU, so no longer makes sense to keep. Ref T73778 Depends on D8010 Maniphest Tasks: T73778 Differential Revision: https://developer.blender.org/D8011 --- intern/cycles/render/object.cpp | 8 -------- 1 file changed, 8 deletions(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 28337ef1a21..7c8b7bf0edc 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -616,7 +616,6 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, dscene->data.bvh.have_motion = state.have_motion; dscene->data.bvh.have_curves = state.have_curves; - dscene->data.bvh.have_instancing = true; } void ObjectManager::device_update(Device *device, @@ -791,7 +790,6 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P bool motion_blur = need_motion == Scene::MOTION_BLUR; bool apply_to_motion = need_motion != Scene::MOTION_PASS; int i = 0; - bool have_instancing = false; foreach (Object *object, scene->objects) { map::iterator it = geometry_users.find(object->geometry); @@ -837,16 +835,10 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P if (geom->transform_negative_scaled) object_flag[i] |= SD_OBJECT_NEGATIVE_SCALE_APPLIED; } - else - have_instancing = true; } - else - have_instancing = true; i++; } - - dscene->data.bvh.have_instancing = have_instancing; } void ObjectManager::tag_update(Scene *scene) -- cgit v1.2.3 From 207338bb58b1a44c531e6d78fad68672c6d3b2e1 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 18 Feb 2020 20:54:41 +0100 Subject: Cycles: port curve-ray intersection from Embree for use in Cycles GPU This keeps render results compatible for combined CPU + GPU rendering. Peformance and quality primitives is quite different than before. There are now two options: * Rounded Ribbon: render hair as flat ribbon with (fake) rounded normals, for fast rendering. Hair curves are subdivided with a fixed number of user specified subdivisions. This gives relatively good results, especially when used with the Principled Hair BSDF and hair viewed from a typical distance. There are artifacts when viewed closed up, though this was also the case with all previous primitives (but different ones). * 3D Curve: render hair as 3D curve, for accurate results when viewing hair close up. This automatically subdivides the curve until it is smooth. This gives higher quality than any of the previous primitives, but does come at a performance cost and is somewhat slower than our previous Thick curves. The main problem here is performance. For CPU and OpenCL rendering performance seems usually quite close or better for similar quality results. However for CUDA and Optix, performance of 3D curve intersection is problematic, with e.g. 1.45x longer render time in Koro (though there is no equivalent quality and rounded ribbons seem fine for that scene). Any help or ideas to optimize this are welcome. Ref T73778 Depends on D8012 Maniphest Tasks: T73778 Differential Revision: https://developer.blender.org/D8013 --- intern/cycles/render/curves.cpp | 12 ++++++------ intern/cycles/render/session.cpp | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp index 0d2be71eed8..7c9bcaa2549 100644 --- a/intern/cycles/render/curves.cpp +++ b/intern/cycles/render/curves.cpp @@ -36,13 +36,12 @@ void curvebounds(float *lower, float *upper, float3 *p, int dim) float *p2 = &p[2].x; float *p3 = &p[3].x; - float fc = 0.71f; + /* Catmull-Rom weights. */ float curve_coef[4]; curve_coef[0] = p1[dim]; - curve_coef[1] = -fc * p0[dim] + fc * p2[dim]; - curve_coef[2] = 2.0f * fc * p0[dim] + (fc - 3.0f) * p1[dim] + (3.0f - 2.0f * fc) * p2[dim] - - fc * p3[dim]; - curve_coef[3] = -fc * p0[dim] + (2.0f - fc) * p1[dim] + (fc - 2.0f) * p2[dim] + fc * p3[dim]; + curve_coef[1] = 0.5f * (-p0[dim] + p2[dim]); + curve_coef[2] = 0.5f * (2 * p0[dim] - 5 * p1[dim] + 4 * p2[dim] - p3[dim]); + curve_coef[3] = 0.5f * (-p0[dim] + 3 * p1[dim] - 3 * p2[dim] + p3[dim]); float discroot = curve_coef[2] * curve_coef[2] - 3 * curve_coef[3] * curve_coef[1]; float ta = -1.0f; @@ -115,7 +114,8 @@ void CurveSystemManager::device_update(Device *device, kcurve->curveflags |= CURVE_KN_RIBBONS; } - kcurve->subdivisions = subdivisions; + /* Matching the tesselation rate limit in Embree. */ + kcurve->subdivisions = clamp(1 << subdivisions, 1, 16); } if (progress.get_cancel()) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index f5bfebbaf78..6caa686847e 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -21,6 +21,7 @@ #include "render/bake.h" #include "render/buffers.h" #include "render/camera.h" +#include "render/curves.h" #include "render/graph.h" #include "render/integrator.h" #include "render/light.h" @@ -773,6 +774,7 @@ DeviceRequestedFeatures Session::get_requested_device_features() */ bool use_motion = scene->need_motion() == Scene::MotionType::MOTION_BLUR; requested_features.use_hair = false; + requested_features.use_hair_thick = (scene->curve_system_manager->curve_shape == CURVE_THICK); requested_features.use_object_motion = false; requested_features.use_camera_motion = use_motion && scene->camera->use_motion(); foreach (Object *object, scene->objects) { -- cgit v1.2.3 From 2c41c8e94fa8740f67dc39150dd1ab66b506adc9 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 10 Jun 2020 19:07:07 +0200 Subject: Cycles: internal refactoring to make thick/ribbon curve separate primitives Also removing the curve system manager which only stored a few curve intersection settings. These are all changes towards making shape and subdivision settings per-object instead of per-scene, but there is more work to do here. Ref T73778 Depends on D8013 Maniphest Tasks: T73778 Differential Revision: https://developer.blender.org/D8014 --- intern/cycles/render/curves.cpp | 72 --------------------------------------- intern/cycles/render/curves.h | 33 ++---------------- intern/cycles/render/geometry.cpp | 13 ++++--- intern/cycles/render/hair.cpp | 1 + intern/cycles/render/hair.h | 1 + intern/cycles/render/object.cpp | 2 -- intern/cycles/render/scene.cpp | 13 +------ intern/cycles/render/scene.h | 12 ++++++- intern/cycles/render/session.cpp | 3 +- 9 files changed, 26 insertions(+), 124 deletions(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp index 7c9bcaa2549..db48d8b6430 100644 --- a/intern/cycles/render/curves.cpp +++ b/intern/cycles/render/curves.cpp @@ -76,76 +76,4 @@ void curvebounds(float *lower, float *upper, float3 *p, int dim) *lower = min(*lower, min(exa, exb)); } -/* Hair System Manager */ - -CurveSystemManager::CurveSystemManager() -{ - curve_shape = CURVE_THICK; - subdivisions = 3; - - use_curves = true; - - need_update = true; - need_mesh_update = false; -} - -CurveSystemManager::~CurveSystemManager() -{ -} - -void CurveSystemManager::device_update(Device *device, - DeviceScene *dscene, - Scene * /*scene*/, - Progress &progress) -{ - if (!need_update) - return; - - device_free(device, dscene); - - progress.set_status("Updating Hair settings", "Copying Hair settings to device"); - - KernelCurves *kcurve = &dscene->data.curve; - - kcurve->curveflags = 0; - - if (use_curves) { - if (curve_shape == CURVE_RIBBON) { - kcurve->curveflags |= CURVE_KN_RIBBONS; - } - - /* Matching the tesselation rate limit in Embree. */ - kcurve->subdivisions = clamp(1 << subdivisions, 1, 16); - } - - if (progress.get_cancel()) - return; - - need_update = false; -} - -void CurveSystemManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/) -{ -} - -bool CurveSystemManager::modified(const CurveSystemManager &CurveSystemManager) -{ - return !(use_curves == CurveSystemManager.use_curves && - subdivisions == CurveSystemManager.subdivisions); -} - -bool CurveSystemManager::modified_mesh(const CurveSystemManager &CurveSystemManager) -{ - return !(use_curves == CurveSystemManager.use_curves); -} - -void CurveSystemManager::tag_update(Scene * /*scene*/) -{ - need_update = true; -} - -void CurveSystemManager::tag_update_mesh() -{ - need_mesh_update = true; -} CCL_NAMESPACE_END diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h index e6b0a3b4706..71c09ba2d2b 100644 --- a/intern/cycles/render/curves.h +++ b/intern/cycles/render/curves.h @@ -20,6 +20,8 @@ #include "util/util_array.h" #include "util/util_types.h" +#include "render/hair.h" + CCL_NAMESPACE_BEGIN class Device; @@ -29,13 +31,6 @@ class Scene; void curvebounds(float *lower, float *upper, float3 *p, int dim); -typedef enum CurveShapeType { - CURVE_RIBBON = 0, - CURVE_THICK = 1, - - CURVE_NUM_SHAPE_TYPES, -} CurveShapeType; - class ParticleCurveData { public: @@ -61,30 +56,6 @@ class ParticleCurveData { array curvekey_time; }; -/* HairSystem Manager */ - -class CurveSystemManager { - public: - CurveShapeType curve_shape; - int subdivisions; - - bool use_curves; - - bool need_update; - bool need_mesh_update; - - CurveSystemManager(); - ~CurveSystemManager(); - - void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); - void device_free(Device *device, DeviceScene *dscene); - bool modified(const CurveSystemManager &CurveSystemManager); - bool modified_mesh(const CurveSystemManager &CurveSystemManager); - - void tag_update(Scene *scene); - void tag_update_mesh(); -}; - CCL_NAMESPACE_END #endif /* __CURVES_H__ */ diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp index f448c2fb07f..797321f6eff 100644 --- a/intern/cycles/render/geometry.cpp +++ b/intern/cycles/render/geometry.cpp @@ -211,8 +211,7 @@ void Geometry::compute_bvh( bparams.num_motion_triangle_steps = params->num_bvh_time_steps; bparams.num_motion_curve_steps = params->num_bvh_time_steps; bparams.bvh_type = params->bvh_type; - bparams.curve_flags = dscene->data.curve.curveflags; - bparams.curve_subdivisions = dscene->data.curve.subdivisions; + bparams.curve_subdivisions = params->curve_subdivisions(); delete bvh; bvh = BVH::create(bparams, geometry, objects); @@ -1026,8 +1025,7 @@ void GeometryManager::device_update_bvh(Device *device, bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps; bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps; bparams.bvh_type = scene->params.bvh_type; - bparams.curve_flags = dscene->data.curve.curveflags; - bparams.curve_subdivisions = dscene->data.curve.subdivisions; + bparams.curve_subdivisions = scene->params.curve_subdivisions(); VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout."; @@ -1103,6 +1101,7 @@ void GeometryManager::device_update_bvh(Device *device, dscene->data.bvh.root = pack.root_index; dscene->data.bvh.bvh_layout = bparams.bvh_layout; dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0); + dscene->data.bvh.curve_subdivisions = scene->params.curve_subdivisions(); bvh->copy_to_device(progress, dscene); @@ -1145,6 +1144,12 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro create_volume_mesh(mesh, progress); } } + + if (geom->type == Geometry::HAIR) { + /* Set curve shape, still a global scene setting for now. */ + Hair *hair = static_cast(geom); + hair->curve_shape = scene->params.hair_shape; + } } need_flags_update = false; diff --git a/intern/cycles/render/hair.cpp b/intern/cycles/render/hair.cpp index 3daa4cc1e35..816c15cf4ef 100644 --- a/intern/cycles/render/hair.cpp +++ b/intern/cycles/render/hair.cpp @@ -294,6 +294,7 @@ NODE_DEFINE(Hair) Hair::Hair() : Geometry(node_type, Geometry::HAIR) { curvekey_offset = 0; + curve_shape = CURVE_RIBBON; } Hair::~Hair() diff --git a/intern/cycles/render/hair.h b/intern/cycles/render/hair.h index 79f77a78753..39d6a34d799 100644 --- a/intern/cycles/render/hair.h +++ b/intern/cycles/render/hair.h @@ -96,6 +96,7 @@ class Hair : public Geometry { /* BVH */ size_t curvekey_offset; + CurveShapeType curve_shape; /* Constructor/Destructor */ Hair(); diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 7c8b7bf0edc..3a8a0cd9a05 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -219,7 +219,6 @@ void Object::tag_update(Scene *scene) } scene->camera->need_flags_update = true; - scene->curve_system_manager->need_update = true; scene->geometry_manager->need_update = true; scene->object_manager->need_update = true; } @@ -844,7 +843,6 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P void ObjectManager::tag_update(Scene *scene) { need_update = true; - scene->curve_system_manager->need_update = true; scene->geometry_manager->need_update = true; scene->light_manager->need_update = true; } diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index f5b68d5a4fe..9016a8d325f 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -108,7 +108,6 @@ Scene::Scene(const SceneParams ¶ms_, Device *device) integrator = new Integrator(); image_manager = new ImageManager(device->info); particle_system_manager = new ParticleSystemManager(); - curve_system_manager = new CurveSystemManager(); bake_manager = new BakeManager(); /* OSL only works on the CPU */ @@ -156,7 +155,6 @@ void Scene::free_memory(bool final) light_manager->device_free(device, &dscene); particle_system_manager->device_free(device, &dscene); - curve_system_manager->device_free(device, &dscene); bake_manager->device_free(device, &dscene); @@ -180,7 +178,6 @@ void Scene::free_memory(bool final) delete shader_manager; delete light_manager; delete particle_system_manager; - delete curve_system_manager; delete image_manager; delete bake_manager; } @@ -230,12 +227,6 @@ void Scene::device_update(Device *device_, Progress &progress) progress.set_status("Updating Objects"); object_manager->device_update(device, &dscene, this, progress); - if (progress.get_cancel() || device->have_error()) - return; - - progress.set_status("Updating Hair Systems"); - curve_system_manager->device_update(device, &dscene, this, progress); - if (progress.get_cancel() || device->have_error()) return; @@ -369,8 +360,7 @@ bool Scene::need_data_update() return (background->need_update || image_manager->need_update || object_manager->need_update || geometry_manager->need_update || light_manager->need_update || lookup_tables->need_update || integrator->need_update || shader_manager->need_update || - particle_system_manager->need_update || curve_system_manager->need_update || - bake_manager->need_update || film->need_update); + particle_system_manager->need_update || bake_manager->need_update || film->need_update); } bool Scene::need_reset() @@ -393,7 +383,6 @@ void Scene::reset() geometry_manager->tag_update(this); light_manager->tag_update(this); particle_system_manager->tag_update(this); - curve_system_manager->tag_update(this); } void Scene::device_free() diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 6b10a901d7b..67616262c03 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -168,6 +168,8 @@ class SceneParams { bool use_bvh_spatial_split; bool use_bvh_unaligned_nodes; int num_bvh_time_steps; + int hair_subdivisions; + CurveShapeType hair_shape; bool persistent_data; int texture_limit; @@ -181,6 +183,8 @@ class SceneParams { use_bvh_spatial_split = false; use_bvh_unaligned_nodes = true; num_bvh_time_steps = 0; + hair_subdivisions = 3; + hair_shape = CURVE_RIBBON; persistent_data = false; texture_limit = 0; background = true; @@ -193,8 +197,15 @@ class SceneParams { use_bvh_spatial_split == params.use_bvh_spatial_split && use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes && num_bvh_time_steps == params.num_bvh_time_steps && + hair_subdivisions == params.hair_subdivisions && hair_shape == params.hair_shape && persistent_data == params.persistent_data && texture_limit == params.texture_limit); } + + int curve_subdivisions() + { + /* Matching the tesselation rate limit in Embree. */ + return clamp(1 << hair_subdivisions, 1, 16); + } }; /* Scene */ @@ -226,7 +237,6 @@ class Scene { GeometryManager *geometry_manager; ObjectManager *object_manager; ParticleSystemManager *particle_system_manager; - CurveSystemManager *curve_system_manager; BakeManager *bake_manager; /* default shaders */ diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 6caa686847e..9d5e57404f0 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -21,7 +21,6 @@ #include "render/bake.h" #include "render/buffers.h" #include "render/camera.h" -#include "render/curves.h" #include "render/graph.h" #include "render/integrator.h" #include "render/light.h" @@ -774,7 +773,7 @@ DeviceRequestedFeatures Session::get_requested_device_features() */ bool use_motion = scene->need_motion() == Scene::MotionType::MOTION_BLUR; requested_features.use_hair = false; - requested_features.use_hair_thick = (scene->curve_system_manager->curve_shape == CURVE_THICK); + requested_features.use_hair_thick = (scene->params.hair_shape == CURVE_THICK); requested_features.use_object_motion = false; requested_features.use_camera_motion = use_motion && scene->camera->use_motion(); foreach (Object *object, scene->objects) { -- cgit v1.2.3 From 0a3bde63006c66b8b8531ed5eccca9bdf5e5dc20 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 31 May 2020 23:49:10 +0200 Subject: Cycles: add denoising settings to the render properties Enabling render and viewport denoising is now both done from the render properties. View layers still can individually be enabled/disabled for denoising and have their own denoising parameters. Note that the denoising engine also affects how denoising data passes are output even if no denoising happens on the render itself, to make the passes compatible with the engine. This includes internal refactoring for how denoising parameters are passed along, trying to avoid code duplication and unclear naming. Ref T76259 --- intern/cycles/render/denoising.cpp | 5 +++-- intern/cycles/render/session.cpp | 38 +++++++++++++++++++++----------------- intern/cycles/render/session.h | 14 +++----------- 3 files changed, 27 insertions(+), 30 deletions(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/denoising.cpp b/intern/cycles/render/denoising.cpp index 93815ebfbc4..4055bc4773b 100644 --- a/intern/cycles/render/denoising.cpp +++ b/intern/cycles/render/denoising.cpp @@ -378,8 +378,9 @@ void DenoiseTask::create_task(DeviceTask &task) /* Denoising parameters. */ task.denoising = denoiser->params; - task.denoising_do_filter = true; - task.denoising_write_passes = false; + task.denoising.type = DENOISER_NLM; + task.denoising.use = true; + task.denoising.store_passes = false; task.denoising_from_render = false; task.denoising_frames.resize(neighbor_frames.size()); diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 9d5e57404f0..f11722ac9a9 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -805,7 +805,7 @@ DeviceRequestedFeatures Session::get_requested_device_features() requested_features.use_baking = bake_manager->get_baking(); requested_features.use_integrator_branched = (scene->integrator->method == Integrator::BRANCHED_PATH); - if (params.run_denoising) { + if (params.denoising.use || params.denoising.store_passes) { requested_features.use_denoising = true; requested_features.use_shadow_tricks = true; } @@ -942,24 +942,31 @@ void Session::set_pause(bool pause_) pause_cond.notify_all(); } -void Session::set_denoising(bool denoising, bool optix_denoising) +void Session::set_denoising(const DenoiseParams &denoising) { + const bool need_denoise = denoising.need_denoising_task(); + + if (need_denoise && !(params.device.denoisers & denoising.type)) { + progress.set_error("Denoiser type not supported by compute device"); + return; + } + /* Lock buffers so no denoising operation is triggered while the settings are changed here. */ thread_scoped_lock buffers_lock(buffers_mutex); - - params.run_denoising = denoising; - params.full_denoising = !optix_denoising; - params.optix_denoising = optix_denoising; + params.denoising = denoising; // TODO(pmours): Query the required overlap value for denoising from the device? - tile_manager.slice_overlap = denoising && !params.background ? 64 : 0; - tile_manager.schedule_denoising = denoising && !buffers; + tile_manager.slice_overlap = need_denoise && !params.background ? 64 : 0; + + /* Schedule per tile denoising for final renders if we are either denoising or + * need prefiltered passes for the native denoiser. */ + tile_manager.schedule_denoising = need_denoise && !buffers; } void Session::set_denoising_start_sample(int sample) { - if (sample != params.denoising_start_sample) { - params.denoising_start_sample = sample; + if (sample != params.denoising.start_sample) { + params.denoising.start_sample = sample; pause_cond.notify_all(); } @@ -1079,10 +1086,10 @@ void Session::update_status_time(bool show_pause, bool show_done) */ substatus += string_printf(", Sample %d/%d", progress.get_current_sample(), num_samples); } - if (params.full_denoising || params.optix_denoising) { + if (params.denoising.use) { substatus += string_printf(", Denoised %d tiles", progress.get_denoised_tiles()); } - else if (params.run_denoising) { + else if (params.denoising.store_passes && params.denoising.type == DENOISER_NLM) { substatus += string_printf(", Prefiltered %d tiles", progress.get_denoised_tiles()); } } @@ -1111,7 +1118,7 @@ bool Session::render_need_denoise(bool &delayed) delayed = false; /* Denoising enabled? */ - if (!params.run_denoising) { + if (!params.denoising.need_denoising_task()) { return false; } @@ -1128,7 +1135,7 @@ bool Session::render_need_denoise(bool &delayed) } /* Do not denoise until the sample at which denoising should start is reached. */ - if (tile_manager.state.sample < params.denoising_start_sample) { + if (tile_manager.state.sample < params.denoising.start_sample) { return false; } @@ -1179,9 +1186,6 @@ void Session::render(bool need_denoise) task.pass_denoising_clean = scene->film->denoising_clean_offset; task.denoising_from_render = true; - task.denoising_do_filter = params.full_denoising; - task.denoising_use_optix = params.optix_denoising; - task.denoising_write_passes = params.write_denoising_passes; if (tile_manager.schedule_denoising) { /* Acquire denoising tiles during rendering. */ diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 2707eed5531..0141629762c 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -62,10 +62,6 @@ class SessionParams { bool display_buffer_linear; - bool run_denoising; - bool write_denoising_passes; - bool full_denoising; - bool optix_denoising; DenoiseParams denoising; double cancel_timeout; @@ -94,11 +90,6 @@ class SessionParams { use_profiling = false; - run_denoising = false; - write_denoising_passes = false; - full_denoising = false; - optix_denoising = false; - display_buffer_linear = false; cancel_timeout = 0.1; @@ -125,7 +116,8 @@ class SessionParams { cancel_timeout == params.cancel_timeout && reset_timeout == params.reset_timeout && text_timeout == params.text_timeout && progressive_update_timeout == params.progressive_update_timeout && - tile_order == params.tile_order && shadingsystem == params.shadingsystem); + tile_order == params.tile_order && shadingsystem == params.shadingsystem && + denoising.type == params.denoising.type); } }; @@ -161,7 +153,7 @@ class Session { void reset(BufferParams ¶ms, int samples); void set_pause(bool pause); void set_samples(int samples); - void set_denoising(bool denoising, bool optix_denoising); + void set_denoising(const DenoiseParams &denoising); void set_denoising_start_sample(int sample); bool update_scene(); -- cgit v1.2.3 From 669befdfbe487f76c65f54e3da0013d140d56893 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 1 Jun 2020 00:11:17 +0200 Subject: Cycles: add Intel OpenImageDenoise support for viewport denoising Compared to Optix denoise, this is usually slower since there is no GPU acceleration. Some optimizations may still be possible, in avoid copies to the GPU and/or denoising less often. The main thing is that this adds viewport denoising support for computers without an NVIDIA GPU (as long as the CPU supports SSE 4.1, which is nearly all of them). Ref T76259 --- intern/cycles/render/session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index f11722ac9a9..c7531adcaf4 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -1086,7 +1086,7 @@ void Session::update_status_time(bool show_pause, bool show_done) */ substatus += string_printf(", Sample %d/%d", progress.get_current_sample(), num_samples); } - if (params.denoising.use) { + if (params.denoising.use && params.denoising.type != DENOISER_OPENIMAGEDENOISE) { substatus += string_printf(", Denoised %d tiles", progress.get_denoised_tiles()); } else if (params.denoising.store_passes && params.denoising.type == DENOISER_NLM) { -- cgit v1.2.3 From b4e1571d0bcf186df979455cf9852dccd325345b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 24 Jun 2020 17:08:01 +0200 Subject: Cleanup: compiler warnings --- intern/cycles/render/object.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 3a8a0cd9a05..405af57effc 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -605,6 +605,10 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, } }); + if (progress.get_cancel()) { + return; + } + dscene->objects.copy_to_device(); if (state.need_motion == Scene::MOTION_PASS) { dscene->object_motion_pass.copy_to_device(); -- cgit v1.2.3 From 0dced1af34e2a714475c24357cf93c2b0147f27f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 23 Jun 2020 21:07:53 +0200 Subject: Fix T78149: Cycles memory leak rendering animation with Embree --- intern/cycles/render/geometry.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp index 797321f6eff..9da1c083ba2 100644 --- a/intern/cycles/render/geometry.cpp +++ b/intern/cycles/render/geometry.cpp @@ -1029,23 +1029,14 @@ void GeometryManager::device_update_bvh(Device *device, VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout."; -#ifdef WITH_EMBREE - if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) { - if (dscene->data.bvh.scene) { - BVHEmbree::destroy(dscene->data.bvh.scene); - } - } -#endif - BVH *bvh = BVH::create(bparams, scene->geometry, scene->objects); bvh->build(progress, &device->stats); if (progress.get_cancel()) { #ifdef WITH_EMBREE - if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) { - if (dscene->data.bvh.scene) { - BVHEmbree::destroy(dscene->data.bvh.scene); - } + if (dscene->data.bvh.scene) { + BVHEmbree::destroy(dscene->data.bvh.scene); + dscene->data.bvh.scene = NULL; } #endif delete bvh; @@ -1417,6 +1408,13 @@ void GeometryManager::device_update(Device *device, void GeometryManager::device_free(Device *device, DeviceScene *dscene) { +#ifdef WITH_EMBREE + if (dscene->data.bvh.scene) { + BVHEmbree::destroy(dscene->data.bvh.scene); + dscene->data.bvh.scene = NULL; + } +#endif + dscene->bvh_nodes.free(); dscene->bvh_leaf_nodes.free(); dscene->object_node.free(); -- cgit v1.2.3 From ec776f18ff70348fd2b13c70e54843f2ba45b599 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Wed, 24 Jun 2020 23:51:57 +0200 Subject: Fix crashing on render end/abort introduced in 0dced1a --- intern/cycles/render/geometry.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp index 9da1c083ba2..291905ac60d 100644 --- a/intern/cycles/render/geometry.cpp +++ b/intern/cycles/render/geometry.cpp @@ -1409,9 +1409,11 @@ void GeometryManager::device_update(Device *device, void GeometryManager::device_free(Device *device, DeviceScene *dscene) { #ifdef WITH_EMBREE - if (dscene->data.bvh.scene) { - BVHEmbree::destroy(dscene->data.bvh.scene); - dscene->data.bvh.scene = NULL; + if (dscene->data.bvh.bvh_layout == BVH_LAYOUT_EMBREE) { + if (dscene->data.bvh.scene) { + BVHEmbree::destroy(dscene->data.bvh.scene); + dscene->data.bvh.scene = NULL; + } } #endif -- cgit v1.2.3 From 6b53e0adbc5fee508da580bdb8feb596e36751bc Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Thu, 25 Jun 2020 11:06:56 +0200 Subject: Better fix for crash ( with gpu only ) on render end/abort introduced in 0dced1a --- intern/cycles/render/geometry.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp index 291905ac60d..3e18661ecf7 100644 --- a/intern/cycles/render/geometry.cpp +++ b/intern/cycles/render/geometry.cpp @@ -1409,12 +1409,11 @@ void GeometryManager::device_update(Device *device, void GeometryManager::device_free(Device *device, DeviceScene *dscene) { #ifdef WITH_EMBREE - if (dscene->data.bvh.bvh_layout == BVH_LAYOUT_EMBREE) { - if (dscene->data.bvh.scene) { + if (dscene->data.bvh.scene) { + if (dscene->data.bvh.bvh_layout == BVH_LAYOUT_EMBREE) BVHEmbree::destroy(dscene->data.bvh.scene); - dscene->data.bvh.scene = NULL; + dscene->data.bvh.scene = NULL; } - } #endif dscene->bvh_nodes.free(); -- cgit v1.2.3 From b30df982d2a47af5536c68df6bdca07de09fa561 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 25 Jun 2020 11:46:32 +0200 Subject: Fix viewport denoising not working if start samples higher than total samples --- intern/cycles/render/session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index c7531adcaf4..8c36d34aeea 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -1135,7 +1135,7 @@ bool Session::render_need_denoise(bool &delayed) } /* Do not denoise until the sample at which denoising should start is reached. */ - if (tile_manager.state.sample < params.denoising.start_sample) { + if (tile_manager.state.sample < min(params.denoising.start_sample, params.samples - 1)) { return false; } -- cgit v1.2.3 From fd5c185bebd5a418634b2a8846f0aeea86327b20 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 25 Jun 2020 23:13:02 +1000 Subject: Cleanup: spelling --- intern/cycles/render/object.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 405af57effc..c45ae5553a8 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -594,7 +594,7 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, numparticles += psys->particles.size(); } - /* Parallel object update, with grain size to avoid too much threadng overhead + /* Parallel object update, with grain size to avoid too much threading overhead * for individual objects. */ static const int OBJECTS_PER_TASK = 32; parallel_for(blocked_range(0, scene->objects.size(), OBJECTS_PER_TASK), -- cgit v1.2.3 From 79c2581bfaf0612f44c44cd09533fc8d231a2d49 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 25 Jun 2020 15:14:30 +0200 Subject: Fix T78238: issue loading existing .blend files with Optix viewport denoiser Also add additional validation to ensure the denoiser is supported before trying to use it. --- intern/cycles/render/session.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 8c36d34aeea..1a94d3e9db7 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -61,8 +61,10 @@ Session::Session(const SessionParams ¶ms_) TaskScheduler::init(params.threads); + /* Create CPU/GPU devices. */ device = Device::create(params.device, stats, profiler, params.background); + /* Create buffers for interactive rendering. */ if (params.background && !params.write_render_cb) { buffers = NULL; display = NULL; @@ -72,6 +74,9 @@ Session::Session(const SessionParams ¶ms_) display = new DisplayBuffer(device, params.display_buffer_linear); } + /* Validate denoising parameters. */ + set_denoising(params.denoising); + session_thread = NULL; scene = NULL; @@ -944,17 +949,21 @@ void Session::set_pause(bool pause_) void Session::set_denoising(const DenoiseParams &denoising) { - const bool need_denoise = denoising.need_denoising_task(); - - if (need_denoise && !(params.device.denoisers & denoising.type)) { - progress.set_error("Denoiser type not supported by compute device"); - return; - } + bool need_denoise = denoising.need_denoising_task(); /* Lock buffers so no denoising operation is triggered while the settings are changed here. */ thread_scoped_lock buffers_lock(buffers_mutex); params.denoising = denoising; + if (!(params.device.denoisers & denoising.type)) { + if (need_denoise) { + progress.set_error("Denoiser type not supported by compute device"); + } + + params.denoising.use = false; + need_denoise = false; + } + // TODO(pmours): Query the required overlap value for denoising from the device? tile_manager.slice_overlap = need_denoise && !params.background ? 64 : 0; -- cgit v1.2.3 From 84f8b47c4c44160de5f59cea9da82d70755209e5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 30 Jun 2020 19:46:27 +1000 Subject: Cleanup: clang-format --- intern/cycles/render/geometry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp index 3e18661ecf7..3d1b6e1d865 100644 --- a/intern/cycles/render/geometry.cpp +++ b/intern/cycles/render/geometry.cpp @@ -1413,7 +1413,7 @@ void GeometryManager::device_free(Device *device, DeviceScene *dscene) if (dscene->data.bvh.bvh_layout == BVH_LAYOUT_EMBREE) BVHEmbree::destroy(dscene->data.bvh.scene); dscene->data.bvh.scene = NULL; - } + } #endif dscene->bvh_nodes.free(); -- cgit v1.2.3 From 4e9ed1dae9647bf45a30d3af546f5a08e7a9b3e3 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 30 Jun 2020 14:07:49 +0200 Subject: Fix T78447: Cycles vertex color node not working with hair --- intern/cycles/render/curves.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'intern/cycles/render') diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h index 71c09ba2d2b..c52fcb9c882 100644 --- a/intern/cycles/render/curves.h +++ b/intern/cycles/render/curves.h @@ -50,7 +50,7 @@ class ParticleCurveData { array curve_keynum; array curve_length; array curve_uv; - array curve_vcol; + array curve_vcol; array curvekey_co; array curvekey_time; -- cgit v1.2.3