Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/CMakeLists.txt2
-rw-r--r--intern/cycles/render/buffers.cpp21
-rw-r--r--intern/cycles/render/buffers.h4
-rw-r--r--intern/cycles/render/coverage.cpp143
-rw-r--r--intern/cycles/render/coverage.h49
-rw-r--r--intern/cycles/render/film.cpp37
-rw-r--r--intern/cycles/render/film.h13
-rw-r--r--intern/cycles/render/object.cpp5
-rw-r--r--intern/cycles/render/object.h1
-rw-r--r--intern/cycles/render/shader.cpp4
10 files changed, 261 insertions, 18 deletions
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index 7d2220f37f9..c0ce7368771 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -15,6 +15,7 @@ set(SRC
buffers.cpp
camera.cpp
constant_fold.cpp
+ coverage.cpp
film.cpp
graph.cpp
image.cpp
@@ -46,6 +47,7 @@ set(SRC_HEADERS
buffers.h
camera.h
constant_fold.h
+ coverage.h
film.h
graph.h
image.h
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index e6021f4b37d..dd20efb3dde 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -233,7 +233,7 @@ bool RenderBuffers::get_denoising_pass_rect(int offset, float exposure, int samp
return true;
}
-bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels)
+bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels, const string &name)
{
if(buffer.data() == NULL) {
return false;
@@ -249,6 +249,14 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int
continue;
}
+ /* Tell Cryptomatte passes apart by their name. */
+ if(pass.type == PASS_CRYPTOMATTE) {
+ if(pass.name != name) {
+ pass_offset += pass.components;
+ continue;
+ }
+ }
+
float *in = buffer.data() + pass_offset;
int pass_stride = params.get_passes_size();
@@ -385,6 +393,17 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int
pixels[3] = f.w*invw;
}
}
+ else if(type == PASS_CRYPTOMATTE) {
+ for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
+ float4 f = make_float4(in[0], in[1], in[2], in[3]);
+ /* x and z contain integer IDs, don't rescale them.
+ y and w contain matte weights, they get scaled. */
+ pixels[0] = f.x;
+ pixels[1] = f.y * scale;
+ pixels[2] = f.z;
+ pixels[3] = f.w * scale;
+ }
+ }
else {
for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
float4 f = make_float4(in[0], in[1], in[2], in[3]);
diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h
index 1b06ffe33a6..a8f019dddd6 100644
--- a/intern/cycles/render/buffers.h
+++ b/intern/cycles/render/buffers.h
@@ -50,7 +50,7 @@ public:
int full_height;
/* passes */
- array<Pass> passes;
+ vector<Pass> passes;
bool denoising_data_pass;
/* If only some light path types should be denoised, an additional pass is needed. */
bool denoising_clean_pass;
@@ -84,7 +84,7 @@ public:
void zero();
bool copy_from_device();
- bool get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels);
+ bool get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels, const string &name);
bool get_denoising_pass_rect(int offset, float exposure, int sample, int components, float *pixels);
};
diff --git a/intern/cycles/render/coverage.cpp b/intern/cycles/render/coverage.cpp
new file mode 100644
index 00000000000..72ef4cda3ff
--- /dev/null
+++ b/intern/cycles/render/coverage.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2018 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "render/coverage.h"
+#include "kernel/kernel_compat_cpu.h"
+#include "kernel/split/kernel_split_data.h"
+#include "kernel/kernel_globals.h"
+#include "kernel/kernel_id_passes.h"
+#include "kernel/kernel_types.h"
+#include "util/util_map.h"
+#include "util/util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+static bool crypomatte_comp(const pair<float, float>& i, const pair<float, float> j) { return i.first > j.first; }
+
+void Coverage::finalize()
+{
+ int pass_offset = 0;
+ if(kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
+ finalize_buffer(coverage_object, pass_offset);
+ pass_offset += kernel_data.film.cryptomatte_depth * 4;
+ }
+ if(kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
+ finalize_buffer(coverage_material, pass_offset);
+ pass_offset += kernel_data.film.cryptomatte_depth * 4;
+ }
+ if(kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
+ finalize_buffer(coverage_asset, pass_offset);
+ }
+}
+
+void Coverage::init_path_trace()
+{
+ kg->coverage_object = kg->coverage_material = kg->coverage_asset = NULL;
+
+ if(kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
+ if(kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
+ coverage_object.clear();
+ coverage_object.resize(tile.w * tile.h);
+ }
+ if(kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
+ coverage_material.clear();
+ coverage_material.resize(tile.w * tile.h);
+ }
+ if(kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
+ coverage_asset.clear();
+ coverage_asset.resize(tile.w * tile.h);
+ }
+ }
+}
+
+void Coverage::init_pixel(int x, int y)
+{
+ if(kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
+ const int pixel_index = tile.w * (y - tile.y) + x - tile.x;
+ if(kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
+ kg->coverage_object = &coverage_object[pixel_index];
+ }
+ if(kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
+ kg->coverage_material = &coverage_material[pixel_index];
+ }
+ if(kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
+ kg->coverage_asset = &coverage_asset[pixel_index];
+ }
+ }
+}
+
+void Coverage::finalize_buffer(vector<CoverageMap> & coverage, const int pass_offset)
+{
+ if(kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
+ flatten_buffer(coverage, pass_offset);
+ }
+ else {
+ sort_buffer(pass_offset);
+ }
+}
+
+void Coverage::flatten_buffer(vector<CoverageMap> &coverage, const int pass_offset)
+{
+ /* Sort the coverage map and write it to the output */
+ int pixel_index = 0;
+ int pass_stride = tile.buffers->params.get_passes_size();
+ for(int y = 0; y < tile.h; ++y) {
+ for(int x = 0; x < tile.w; ++x) {
+ const CoverageMap& pixel = coverage[pixel_index];
+ if(!pixel.empty()) {
+ /* buffer offset */
+ int index = x + y * tile.stride;
+ float *buffer = (float*)tile.buffer + index*pass_stride;
+
+ /* sort the cryptomatte pixel */
+ vector<pair<float, float> > sorted_pixel;
+ for(CoverageMap::const_iterator it = pixel.begin(); it != pixel.end(); ++it) {
+ sorted_pixel.push_back(std::make_pair(it->second, it->first));
+ }
+ sort(sorted_pixel.begin(), sorted_pixel.end(), crypomatte_comp);
+ int num_slots = 2 * (kernel_data.film.cryptomatte_depth);
+ if(sorted_pixel.size() > num_slots) {
+ float leftover = 0.0f;
+ for(vector<pair<float, float> >::iterator it = sorted_pixel.begin()+num_slots; it != sorted_pixel.end(); ++it) {
+ leftover += it->first;
+ }
+ sorted_pixel[num_slots-1].first += leftover;
+ }
+ int limit = min(num_slots, sorted_pixel.size());
+ for(int i = 0; i < limit; ++i) {
+ kernel_write_id_slots(buffer + kernel_data.film.pass_cryptomatte + pass_offset, 2 * (kernel_data.film.cryptomatte_depth), sorted_pixel[i].second, sorted_pixel[i].first);
+ }
+ }
+ ++pixel_index;
+ }
+ }
+}
+
+void Coverage::sort_buffer(const int pass_offset)
+{
+ /* Sort the coverage map and write it to the output */
+ int pass_stride = tile.buffers->params.get_passes_size();
+ for(int y = 0; y < tile.h; ++y) {
+ for(int x = 0; x < tile.w; ++x) {
+ /* buffer offset */
+ int index = x + y*tile.stride;
+ float *buffer = (float*)tile.buffer + index*pass_stride;
+ kernel_sort_id_slots(buffer + kernel_data.film.pass_cryptomatte + pass_offset, 2 * (kernel_data.film.cryptomatte_depth));
+ }
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/render/coverage.h b/intern/cycles/render/coverage.h
new file mode 100644
index 00000000000..16176ce4beb
--- /dev/null
+++ b/intern/cycles/render/coverage.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2018 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "render/buffers.h"
+#include "kernel/kernel_compat_cpu.h"
+#include "kernel/split/kernel_split_data.h"
+#include "kernel/kernel_globals.h"
+#include "util/util_map.h"
+#include "util/util_vector.h"
+
+#ifndef __COVERAGE_H__
+#define __COVERAGE_H__
+
+CCL_NAMESPACE_BEGIN
+
+class Coverage {
+public:
+ Coverage(KernelGlobals *kg_, RenderTile &tile_) : kg(kg_), tile(tile_) { }
+ void init_path_trace();
+ void init_pixel(int x, int y);
+ void finalize();
+private:
+ vector<CoverageMap>coverage_object;
+ vector<CoverageMap>coverage_material;
+ vector<CoverageMap>coverage_asset;
+ KernelGlobals *kg;
+ RenderTile &tile;
+ void finalize_buffer(vector<CoverageMap>&coverage, const int pass_offset);
+ void flatten_buffer(vector<CoverageMap>&coverage, const int pass_offset);
+ void sort_buffer(const int pass_offset);
+};
+
+
+CCL_NAMESPACE_END
+
+#endif /* __COVERAGE_H__ */
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 8f3596ade58..d0f15496e50 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -38,11 +38,14 @@ static bool compare_pass_order(const Pass& a, const Pass& b)
return (a.components > b.components);
}
-void Pass::add(PassType type, array<Pass>& passes)
+void Pass::add(PassType type, vector<Pass>& passes, const char *name)
{
- for(size_t i = 0; i < passes.size(); i++)
- if(passes[i].type == type)
+ for(size_t i = 0; i < passes.size(); i++) {
+ if(passes[i].type == type &&
+ (name ? (passes[i].name == name) : passes[i].name.empty())) {
return;
+ }
+ }
Pass pass;
@@ -50,6 +53,9 @@ void Pass::add(PassType type, array<Pass>& passes)
pass.filter = true;
pass.exposure = false;
pass.divide_type = PASS_NONE;
+ if(name) {
+ pass.name = name;
+ }
switch(type) {
case PASS_NONE:
@@ -155,13 +161,15 @@ void Pass::add(PassType type, array<Pass>& passes)
pass.components = 4;
pass.exposure = true;
break;
-
+ case PASS_CRYPTOMATTE:
+ pass.components = 4;
+ break;
default:
assert(false);
break;
}
- passes.push_back_slow(pass);
+ passes.push_back(pass);
/* order from by components, to ensure alignment so passes with size 4
* come first and then passes with size 1 */
@@ -171,19 +179,19 @@ void Pass::add(PassType type, array<Pass>& passes)
Pass::add(pass.divide_type, passes);
}
-bool Pass::equals(const array<Pass>& A, const array<Pass>& B)
+bool Pass::equals(const vector<Pass>& A, const vector<Pass>& B)
{
if(A.size() != B.size())
return false;
for(int i = 0; i < A.size(); i++)
- if(A[i].type != B[i].type)
+ if(A[i].type != B[i].type || A[i].name != B[i].name)
return false;
return true;
}
-bool Pass::contains(const array<Pass>& passes, PassType type)
+bool Pass::contains(const vector<Pass>& passes, PassType type)
{
for(size_t i = 0; i < passes.size(); i++)
if(passes[i].type == type)
@@ -290,6 +298,7 @@ Film::Film()
use_light_visibility = false;
filter_table_offset = TABLE_OFFSET_INVALID;
+ cryptomatte_passes = CRYPT_NONE;
need_update = true;
}
@@ -314,6 +323,8 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kfilm->pass_stride = 0;
kfilm->use_light_pass = use_light_visibility || use_sample_clamp;
+ bool have_cryptomatte = false;
+
for(size_t i = 0; i < passes.size(); i++) {
Pass& pass = passes[i];
@@ -434,7 +445,10 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
#endif
case PASS_RENDER_TIME:
break;
-
+ case PASS_CRYPTOMATTE:
+ kfilm->pass_cryptomatte = have_cryptomatte ? min(kfilm->pass_cryptomatte, kfilm->pass_stride) : kfilm->pass_stride;
+ have_cryptomatte = true;
+ break;
default:
assert(false);
break;
@@ -471,6 +485,9 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kfilm->mist_inv_depth = (mist_depth > 0.0f)? 1.0f/mist_depth: 0.0f;
kfilm->mist_falloff = mist_falloff;
+ kfilm->cryptomatte_passes = cryptomatte_passes;
+ kfilm->cryptomatte_depth = cryptomatte_depth;
+
pass_stride = kfilm->pass_stride;
denoising_data_offset = kfilm->pass_denoising_data;
denoising_clean_offset = kfilm->pass_denoising_clean;
@@ -490,7 +507,7 @@ bool Film::modified(const Film& film)
return !Node::equals(film) || !Pass::equals(passes, film.passes);
}
-void Film::tag_passes_update(Scene *scene, const array<Pass>& passes_)
+void Film::tag_passes_update(Scene *scene, const vector<Pass>& passes_)
{
if(Pass::contains(passes, PASS_UV) != Pass::contains(passes_, PASS_UV)) {
scene->mesh_manager->tag_update(scene);
diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h
index 6ab2eea79b8..57f1bf4eb64 100644
--- a/intern/cycles/render/film.h
+++ b/intern/cycles/render/film.h
@@ -45,10 +45,11 @@ public:
bool filter;
bool exposure;
PassType divide_type;
+ string name;
- static void add(PassType type, array<Pass>& passes);
- static bool equals(const array<Pass>& A, const array<Pass>& B);
- static bool contains(const array<Pass>& passes, PassType);
+ static void add(PassType type, vector<Pass>& passes, const char* name = NULL);
+ static bool equals(const vector<Pass>& A, const vector<Pass>& B);
+ static bool contains(const vector<Pass>& passes, PassType);
};
class Film : public Node {
@@ -56,7 +57,7 @@ public:
NODE_DECLARE
float exposure;
- array<Pass> passes;
+ vector<Pass> passes;
bool denoising_data_pass;
bool denoising_clean_pass;
int denoising_flags;
@@ -76,6 +77,8 @@ public:
bool use_light_visibility;
bool use_sample_clamp;
+ CryptomatteType cryptomatte_passes;
+ int cryptomatte_depth;
bool need_update;
@@ -86,7 +89,7 @@ public:
void device_free(Device *device, DeviceScene *dscene, Scene *scene);
bool modified(const Film& film);
- void tag_passes_update(Scene *scene, const array<Pass>& passes_);
+ void tag_passes_update(Scene *scene, const vector<Pass>& passes_);
void tag_update(Scene *scene);
};
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index e3f35c366d6..a56a8a6ec58 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -28,6 +28,7 @@
#include "util/util_map.h"
#include "util/util_progress.h"
#include "util/util_vector.h"
+#include "util/util_murmurhash.h"
#include "subd/subd_patch_table.h"
@@ -483,6 +484,10 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
kobject.numverts = mesh->verts.size();
kobject.patch_map_offset = 0;
kobject.attribute_map_offset = 0;
+ uint32_t hash_name = util_murmur_hash3(ob->name.c_str(), ob->name.length(), 0);
+ uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
+ kobject.cryptomatte_object = util_hash_to_float(hash_name);
+ kobject.cryptomatte_asset = util_hash_to_float(hash_asset);
/* Object flag. */
if(ob->use_holdout) {
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index b80c4aef70b..bd44b35aba3 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -48,6 +48,7 @@ public:
BoundBox bounds;
uint random_id;
int pass_id;
+ ustring asset_name;
vector<ParamValue> attributes;
uint visibility;
array<Transform> motion;
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index ac605305b94..8d0cec7b14e 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -30,6 +30,7 @@
#include "render/tables.h"
#include "util/util_foreach.h"
+#include "util/util_murmurhash.h"
#ifdef WITH_OCIO
# include <OpenColorIO/OpenColorIO.h>
@@ -523,12 +524,15 @@ void ShaderManager::device_update_common(Device *device,
if(shader->is_constant_emission(&constant_emission))
flag |= SD_HAS_CONSTANT_EMISSION;
+ uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
+
/* regular shader */
kshader->flags = flag;
kshader->pass_id = shader->pass_id;
kshader->constant_emission[0] = constant_emission.x;
kshader->constant_emission[1] = constant_emission.y;
kshader->constant_emission[2] = constant_emission.z;
+ kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id);
kshader++;
has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;