123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /*
- * 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
|