Merge branch 'master' into blender2.8
[blender.git] / intern / cycles / render / coverage.cpp
1 /*
2  * Copyright 2018 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "render/coverage.h"
18 #include "kernel/kernel_compat_cpu.h"
19 #include "kernel/split/kernel_split_data.h"
20 #include "kernel/kernel_globals.h"
21 #include "kernel/kernel_id_passes.h"
22 #include "kernel/kernel_types.h"
23 #include "util/util_map.h"
24 #include "util/util_vector.h"
25
26 CCL_NAMESPACE_BEGIN
27
28 static bool crypomatte_comp(const pair<float, float>& i, const pair<float, float> j) { return i.first > j.first; }
29
30 void Coverage::finalize()
31 {
32         int pass_offset = 0;
33         if(kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
34                 finalize_buffer(coverage_object, pass_offset);
35                 pass_offset += kernel_data.film.cryptomatte_depth * 4;
36         }
37         if(kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
38                 finalize_buffer(coverage_material, pass_offset);
39                 pass_offset += kernel_data.film.cryptomatte_depth * 4;
40         }
41         if(kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
42                 finalize_buffer(coverage_asset, pass_offset);
43         }
44 }
45
46 void Coverage::init_path_trace()
47 {
48         kg->coverage_object = kg->coverage_material =  kg->coverage_asset = NULL;
49
50         if(kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
51                 if(kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
52                         coverage_object.clear();
53                         coverage_object.resize(tile.w * tile.h);
54                 }
55                 if(kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
56                         coverage_material.clear();
57                         coverage_material.resize(tile.w * tile.h);
58                 }
59                 if(kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
60                         coverage_asset.clear();
61                         coverage_asset.resize(tile.w * tile.h);
62                 }
63         }
64 }
65
66 void Coverage::init_pixel(int x, int y)
67 {
68         if(kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
69                 const int pixel_index = tile.w * (y - tile.y) + x - tile.x;
70                 if(kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
71                         kg->coverage_object = &coverage_object[pixel_index];
72                 }
73                 if(kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
74                         kg->coverage_material = &coverage_material[pixel_index];
75                 }
76                 if(kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
77                         kg->coverage_asset = &coverage_asset[pixel_index];
78                 }
79         }
80 }
81
82 void Coverage::finalize_buffer(vector<CoverageMap> & coverage, const int pass_offset)
83 {
84         if(kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
85                 flatten_buffer(coverage, pass_offset);
86         }
87         else {
88                 sort_buffer(pass_offset);
89         }
90 }
91
92 void Coverage::flatten_buffer(vector<CoverageMap> &coverage, const int pass_offset)
93 {
94         /* Sort the coverage map and write it to the output */
95         int pixel_index = 0;
96         int pass_stride = tile.buffers->params.get_passes_size();
97         for(int y = 0; y < tile.h; ++y) {
98                 for(int x = 0; x < tile.w; ++x) {
99                         const CoverageMap& pixel = coverage[pixel_index];
100                         if(!pixel.empty()) {
101                                 /* buffer offset */
102                                 int index = x + y * tile.stride;
103                                 float *buffer = (float*)tile.buffer + index*pass_stride;
104
105                                 /* sort the cryptomatte pixel */
106                                 vector<pair<float, float> > sorted_pixel;
107                                 for(CoverageMap::const_iterator it = pixel.begin(); it != pixel.end(); ++it) {
108                                         sorted_pixel.push_back(std::make_pair(it->second, it->first));
109                                 }
110                                 sort(sorted_pixel.begin(), sorted_pixel.end(), crypomatte_comp);
111                                 int num_slots = 2 * (kernel_data.film.cryptomatte_depth);
112                                 if(sorted_pixel.size() > num_slots) {
113                                         float leftover = 0.0f;
114                                         for(vector<pair<float, float> >::iterator it = sorted_pixel.begin()+num_slots; it != sorted_pixel.end(); ++it) {
115                                                 leftover += it->first;
116                                         }
117                                         sorted_pixel[num_slots-1].first += leftover;
118                                 }
119                                 int limit = min(num_slots, sorted_pixel.size());
120                                 for(int i = 0; i < limit; ++i) {
121                                         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);
122                                 }
123                         }
124                         ++pixel_index;
125                 }
126         }
127 }
128
129 void Coverage::sort_buffer(const int pass_offset)
130 {
131         /* Sort the coverage map and write it to the output */
132         int pass_stride = tile.buffers->params.get_passes_size();
133         for(int y = 0; y < tile.h; ++y) {
134                 for(int x = 0; x < tile.w; ++x) {
135                         /* buffer offset */
136                         int index = x + y*tile.stride;
137                         float *buffer = (float*)tile.buffer + index*pass_stride;
138                         kernel_sort_id_slots(buffer + kernel_data.film.pass_cryptomatte + pass_offset, 2 * (kernel_data.film.cryptomatte_depth));
139                 }
140         }
141 }
142
143 CCL_NAMESPACE_END