diff options
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/CMakeLists.txt | 2 | ||||
-rw-r--r-- | intern/cycles/render/curves.cpp | 110 | ||||
-rw-r--r-- | intern/cycles/render/curves.h | 62 | ||||
-rw-r--r-- | intern/cycles/render/denoising.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/render/geometry.cpp | 41 | ||||
-rw-r--r-- | intern/cycles/render/hair.cpp | 1 | ||||
-rw-r--r-- | intern/cycles/render/hair.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/image.cpp | 1 | ||||
-rw-r--r-- | intern/cycles/render/image.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/image_sky.cpp | 91 | ||||
-rw-r--r-- | intern/cycles/render/image_sky.h | 49 | ||||
-rw-r--r-- | intern/cycles/render/integrator.cpp | 1 | ||||
-rw-r--r-- | intern/cycles/render/light.cpp | 140 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 199 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 9 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 82 | ||||
-rw-r--r-- | intern/cycles/render/scene.cpp | 13 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 12 | ||||
-rw-r--r-- | intern/cycles/render/session.cpp | 46 | ||||
-rw-r--r-- | intern/cycles/render/session.h | 14 | ||||
-rw-r--r-- | intern/cycles/render/shader.cpp | 1 | ||||
-rw-r--r-- | intern/cycles/render/svm.cpp | 3 |
22 files changed, 490 insertions, 396 deletions
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/curves.cpp b/intern/cycles/render/curves.cpp index 1907bb33d06..db48d8b6430 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; @@ -77,105 +76,4 @@ void curvebounds(float *lower, float *upper, float3 *p, int dim) *lower = min(*lower, min(exa, exb)); } -/* Hair System Manager */ - -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; -} - -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 (primitive == CURVE_SEGMENTS || primitive == CURVE_RIBBONS) - kcurve->curveflags |= CURVE_KN_INTERPOLATE; - if (primitive == CURVE_RIBBONS) - 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) - kcurve->curveflags |= CURVE_KN_BACKFACING; - if (use_encasing) - kcurve->curveflags |= CURVE_KN_ENCLOSEFILTER; - - kcurve->subdivisions = subdivisions; - } - - if (progress.get_cancel()) - return; - - need_update = false; -} - -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); -} - -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); -} - -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 ade289a402e..c52fcb9c882 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,33 +31,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, - - 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: @@ -75,43 +50,12 @@ class ParticleCurveData { array<int> curve_keynum; array<float> curve_length; array<float2> curve_uv; - array<float3> curve_vcol; + array<float4> curve_vcol; array<float3> curvekey_co; array<float> curvekey_time; }; -/* HairSystem Manager */ - -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; - - 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/denoising.cpp b/intern/cycles/render/denoising.cpp index 4d819d1119e..4055bc4773b 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 <OpenImageIO/filesystem.h> @@ -377,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/geometry.cpp b/intern/cycles/render/geometry.cpp index d46ed430c4f..3d1b6e1d865 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" @@ -212,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); @@ -1027,28 +1025,18 @@ 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."; -#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; @@ -1104,6 +1092,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); @@ -1146,6 +1135,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<Hair *>(geom); + hair->curve_shape = scene->params.hair_shape; + } } need_flags_update = false; @@ -1413,6 +1408,14 @@ void GeometryManager::device_update(Device *device, void GeometryManager::device_free(Device *device, DeviceScene *dscene) { +#ifdef WITH_EMBREE + 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; + } +#endif + dscene->bvh_nodes.free(); dscene->bvh_leaf_nodes.free(); dscene->object_node.free(); 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/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/image_sky.cpp b/intern/cycles/render/image_sky.cpp new file mode 100644 index 00000000000..442e1d7941f --- /dev/null +++ b/intern/cycles/render/image_sky.cpp @@ -0,0 +1,91 @@ +/* + * 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" +#include "util/util_task.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 rows_per_task = divide_up(1024, width); + parallel_for(blocked_range<size_t>(0, height, rows_per_task), + [&](const blocked_range<size_t> &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; +} + +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/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 cb7474017fa..c0615c6217b 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 @@ -450,6 +451,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 +495,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 +516,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 +570,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 +583,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 +665,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<float3> pixels; shade_background_pixels(device, dscene, res.x, res.y, pixels, progress); @@ -624,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<size_t>(0, res.y, rows_per_task), + [&](const blocked_range<size_t> &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/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 { diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 61deef4cd76..c45ae5553a8 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" @@ -77,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. */ @@ -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; } @@ -550,41 +549,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; @@ -630,28 +594,19 @@ 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 threading overhead + * for individual objects. */ + static const int OBJECTS_PER_TASK = 32; + parallel_for(blocked_range<size_t>(0, scene->objects.size(), OBJECTS_PER_TASK), + [&](const blocked_range<size_t> &r) { + for (size_t i = r.begin(); i != r.end(); i++) { + Object *ob = state.scene->objects[i]; + device_update_object_transform(&state, ob); + } + }); + + if (progress.get_cancel()) { + return; } dscene->objects.copy_to_device(); @@ -664,7 +619,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, @@ -839,7 +793,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<Geometry *, int>::iterator it = geometry_users.find(object->geometry); @@ -885,22 +838,15 @@ 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) { 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; } @@ -233,12 +230,6 @@ void Scene::device_update(Device *device_, Progress &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; - progress.set_status("Updating Particle Systems"); particle_system_manager->device_update(device, &dscene, this, progress); @@ -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 f5bfebbaf78..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; @@ -773,6 +778,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->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) { @@ -804,7 +810,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; } @@ -941,24 +947,35 @@ 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) { + 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.run_denoising = denoising; - params.full_denoising = !optix_denoising; - params.optix_denoising = optix_denoising; + params.denoising.use = false; + need_denoise = false; + } // 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(); } @@ -1078,10 +1095,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 && params.denoising.type != DENOISER_OPENIMAGEDENOISE) { 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()); } } @@ -1110,7 +1127,7 @@ bool Session::render_need_denoise(bool &delayed) delayed = false; /* Denoising enabled? */ - if (!params.run_denoising) { + if (!params.denoising.need_denoising_task()) { return false; } @@ -1127,7 +1144,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; } @@ -1178,9 +1195,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(); 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 <OpenColorIO/OpenColorIO.h> 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(); |