blender/intern/cycles/scene/pass.cpp
Brecht Van Lommel d7d40745fa Cycles: changes to source code folders structure
* Split render/ into scene/ and session/. The scene/ folder now contains the
  scene and its nodes. The session/ folder contains the render session and
  associated data structures like drivers and render buffers.
* Move top level kernel headers into new folders kernel/camera/, kernel/film/,
  kernel/light/, kernel/sample/, kernel/util/
* Move integrator related kernel headers into kernel/integrator/
* Move OSL shaders from kernel/shaders/ to kernel/osl/shaders/

For patches and branches, git merge and rebase should be able to detect the
renames and move over code to the right file.
2021-10-26 15:36:39 +02:00

427 lines
13 KiB
C++

/*
* Copyright 2011-2021 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 "scene/pass.h"
#include "util/util_algorithm.h"
#include "util/util_logging.h"
CCL_NAMESPACE_BEGIN
const char *pass_type_as_string(const PassType type)
{
const int type_int = static_cast<int>(type);
const NodeEnum *type_enum = Pass::get_type_enum();
if (!type_enum->exists(type_int)) {
LOG(DFATAL) << "Unhandled pass type " << static_cast<int>(type) << ", not supposed to happen.";
return "UNKNOWN";
}
return (*type_enum)[type_int].c_str();
}
const char *pass_mode_as_string(PassMode mode)
{
switch (mode) {
case PassMode::NOISY:
return "NOISY";
case PassMode::DENOISED:
return "DENOISED";
}
LOG(DFATAL) << "Unhandled pass mode " << static_cast<int>(mode) << ", should never happen.";
return "UNKNOWN";
}
std::ostream &operator<<(std::ostream &os, PassMode mode)
{
os << pass_mode_as_string(mode);
return os;
}
const NodeEnum *Pass::get_type_enum()
{
static NodeEnum pass_type_enum;
if (pass_type_enum.empty()) {
/* Light Passes. */
pass_type_enum.insert("combined", PASS_COMBINED);
pass_type_enum.insert("emission", PASS_EMISSION);
pass_type_enum.insert("background", PASS_BACKGROUND);
pass_type_enum.insert("ao", PASS_AO);
pass_type_enum.insert("shadow", PASS_SHADOW);
pass_type_enum.insert("diffuse", PASS_DIFFUSE);
pass_type_enum.insert("diffuse_direct", PASS_DIFFUSE_DIRECT);
pass_type_enum.insert("diffuse_indirect", PASS_DIFFUSE_INDIRECT);
pass_type_enum.insert("glossy", PASS_GLOSSY);
pass_type_enum.insert("glossy_direct", PASS_GLOSSY_DIRECT);
pass_type_enum.insert("glossy_indirect", PASS_GLOSSY_INDIRECT);
pass_type_enum.insert("transmission", PASS_TRANSMISSION);
pass_type_enum.insert("transmission_direct", PASS_TRANSMISSION_DIRECT);
pass_type_enum.insert("transmission_indirect", PASS_TRANSMISSION_INDIRECT);
pass_type_enum.insert("volume", PASS_VOLUME);
pass_type_enum.insert("volume_direct", PASS_VOLUME_DIRECT);
pass_type_enum.insert("volume_indirect", PASS_VOLUME_INDIRECT);
/* Data passes. */
pass_type_enum.insert("depth", PASS_DEPTH);
pass_type_enum.insert("position", PASS_POSITION);
pass_type_enum.insert("normal", PASS_NORMAL);
pass_type_enum.insert("roughness", PASS_ROUGHNESS);
pass_type_enum.insert("uv", PASS_UV);
pass_type_enum.insert("object_id", PASS_OBJECT_ID);
pass_type_enum.insert("material_id", PASS_MATERIAL_ID);
pass_type_enum.insert("motion", PASS_MOTION);
pass_type_enum.insert("motion_weight", PASS_MOTION_WEIGHT);
pass_type_enum.insert("cryptomatte", PASS_CRYPTOMATTE);
pass_type_enum.insert("aov_color", PASS_AOV_COLOR);
pass_type_enum.insert("aov_value", PASS_AOV_VALUE);
pass_type_enum.insert("adaptive_aux_buffer", PASS_ADAPTIVE_AUX_BUFFER);
pass_type_enum.insert("sample_count", PASS_SAMPLE_COUNT);
pass_type_enum.insert("diffuse_color", PASS_DIFFUSE_COLOR);
pass_type_enum.insert("glossy_color", PASS_GLOSSY_COLOR);
pass_type_enum.insert("transmission_color", PASS_TRANSMISSION_COLOR);
pass_type_enum.insert("mist", PASS_MIST);
pass_type_enum.insert("denoising_normal", PASS_DENOISING_NORMAL);
pass_type_enum.insert("denoising_albedo", PASS_DENOISING_ALBEDO);
pass_type_enum.insert("denoising_depth", PASS_DENOISING_DEPTH);
pass_type_enum.insert("shadow_catcher", PASS_SHADOW_CATCHER);
pass_type_enum.insert("shadow_catcher_sample_count", PASS_SHADOW_CATCHER_SAMPLE_COUNT);
pass_type_enum.insert("shadow_catcher_matte", PASS_SHADOW_CATCHER_MATTE);
pass_type_enum.insert("bake_primitive", PASS_BAKE_PRIMITIVE);
pass_type_enum.insert("bake_differential", PASS_BAKE_DIFFERENTIAL);
}
return &pass_type_enum;
}
const NodeEnum *Pass::get_mode_enum()
{
static NodeEnum pass_mode_enum;
if (pass_mode_enum.empty()) {
pass_mode_enum.insert("noisy", static_cast<int>(PassMode::NOISY));
pass_mode_enum.insert("denoised", static_cast<int>(PassMode::DENOISED));
}
return &pass_mode_enum;
}
NODE_DEFINE(Pass)
{
NodeType *type = NodeType::add("pass", create);
const NodeEnum *pass_type_enum = get_type_enum();
const NodeEnum *pass_mode_enum = get_mode_enum();
SOCKET_ENUM(type, "Type", *pass_type_enum, PASS_COMBINED);
SOCKET_ENUM(mode, "Mode", *pass_mode_enum, static_cast<int>(PassMode::DENOISED));
SOCKET_STRING(name, "Name", ustring());
SOCKET_BOOLEAN(include_albedo, "Include Albedo", false);
return type;
}
Pass::Pass() : Node(get_node_type()), is_auto_(false)
{
}
PassInfo Pass::get_info() const
{
return get_info(type, include_albedo);
}
bool Pass::is_written() const
{
return get_info().is_written;
}
PassInfo Pass::get_info(const PassType type, const bool include_albedo)
{
PassInfo pass_info;
pass_info.use_filter = true;
pass_info.use_exposure = false;
pass_info.divide_type = PASS_NONE;
pass_info.use_compositing = false;
pass_info.use_denoising_albedo = true;
switch (type) {
case PASS_NONE:
pass_info.num_components = 0;
break;
case PASS_COMBINED:
pass_info.num_components = 4;
pass_info.use_exposure = true;
pass_info.support_denoise = true;
break;
case PASS_DEPTH:
pass_info.num_components = 1;
pass_info.use_filter = false;
break;
case PASS_MIST:
pass_info.num_components = 1;
break;
case PASS_POSITION:
pass_info.num_components = 3;
break;
case PASS_NORMAL:
pass_info.num_components = 3;
break;
case PASS_ROUGHNESS:
pass_info.num_components = 1;
break;
case PASS_UV:
pass_info.num_components = 3;
break;
case PASS_MOTION:
pass_info.num_components = 4;
pass_info.divide_type = PASS_MOTION_WEIGHT;
break;
case PASS_MOTION_WEIGHT:
pass_info.num_components = 1;
break;
case PASS_OBJECT_ID:
case PASS_MATERIAL_ID:
pass_info.num_components = 1;
pass_info.use_filter = false;
break;
case PASS_EMISSION:
case PASS_BACKGROUND:
pass_info.num_components = 3;
pass_info.use_exposure = true;
break;
case PASS_AO:
pass_info.num_components = 3;
break;
case PASS_SHADOW:
pass_info.num_components = 3;
pass_info.use_exposure = false;
break;
case PASS_DIFFUSE_COLOR:
case PASS_GLOSSY_COLOR:
case PASS_TRANSMISSION_COLOR:
pass_info.num_components = 3;
break;
case PASS_DIFFUSE:
pass_info.num_components = 3;
pass_info.use_exposure = true;
pass_info.direct_type = PASS_DIFFUSE_DIRECT;
pass_info.indirect_type = PASS_DIFFUSE_INDIRECT;
pass_info.divide_type = (!include_albedo) ? PASS_DIFFUSE_COLOR : PASS_NONE;
pass_info.use_compositing = true;
pass_info.is_written = false;
break;
case PASS_DIFFUSE_DIRECT:
case PASS_DIFFUSE_INDIRECT:
pass_info.num_components = 3;
pass_info.use_exposure = true;
pass_info.divide_type = (!include_albedo) ? PASS_DIFFUSE_COLOR : PASS_NONE;
pass_info.use_compositing = true;
break;
case PASS_GLOSSY:
pass_info.num_components = 3;
pass_info.use_exposure = true;
pass_info.direct_type = PASS_GLOSSY_DIRECT;
pass_info.indirect_type = PASS_GLOSSY_INDIRECT;
pass_info.divide_type = (!include_albedo) ? PASS_GLOSSY_COLOR : PASS_NONE;
pass_info.use_compositing = true;
pass_info.is_written = false;
break;
case PASS_GLOSSY_DIRECT:
case PASS_GLOSSY_INDIRECT:
pass_info.num_components = 3;
pass_info.use_exposure = true;
pass_info.divide_type = (!include_albedo) ? PASS_GLOSSY_COLOR : PASS_NONE;
pass_info.use_compositing = true;
break;
case PASS_TRANSMISSION:
pass_info.num_components = 3;
pass_info.use_exposure = true;
pass_info.direct_type = PASS_TRANSMISSION_DIRECT;
pass_info.indirect_type = PASS_TRANSMISSION_INDIRECT;
pass_info.divide_type = (!include_albedo) ? PASS_TRANSMISSION_COLOR : PASS_NONE;
pass_info.use_compositing = true;
pass_info.is_written = false;
break;
case PASS_TRANSMISSION_DIRECT:
case PASS_TRANSMISSION_INDIRECT:
pass_info.num_components = 3;
pass_info.use_exposure = true;
pass_info.divide_type = (!include_albedo) ? PASS_TRANSMISSION_COLOR : PASS_NONE;
pass_info.use_compositing = true;
break;
case PASS_VOLUME:
pass_info.num_components = 3;
pass_info.use_exposure = true;
pass_info.direct_type = PASS_VOLUME_DIRECT;
pass_info.indirect_type = PASS_VOLUME_INDIRECT;
pass_info.use_compositing = true;
pass_info.is_written = false;
break;
case PASS_VOLUME_DIRECT:
case PASS_VOLUME_INDIRECT:
pass_info.num_components = 3;
pass_info.use_exposure = true;
break;
case PASS_CRYPTOMATTE:
pass_info.num_components = 4;
break;
case PASS_DENOISING_NORMAL:
pass_info.num_components = 3;
break;
case PASS_DENOISING_ALBEDO:
pass_info.num_components = 3;
break;
case PASS_DENOISING_DEPTH:
pass_info.num_components = 1;
break;
case PASS_SHADOW_CATCHER:
pass_info.num_components = 3;
pass_info.use_exposure = true;
pass_info.use_compositing = true;
pass_info.use_denoising_albedo = false;
pass_info.support_denoise = true;
break;
case PASS_SHADOW_CATCHER_SAMPLE_COUNT:
pass_info.num_components = 1;
break;
case PASS_SHADOW_CATCHER_MATTE:
pass_info.num_components = 4;
pass_info.use_exposure = true;
pass_info.support_denoise = true;
/* Without shadow catcher approximation compositing is not needed.
* Since we don't know here whether approximation is used or not, leave the decision up to
* the caller which will know that. */
break;
case PASS_ADAPTIVE_AUX_BUFFER:
pass_info.num_components = 4;
break;
case PASS_SAMPLE_COUNT:
pass_info.num_components = 1;
pass_info.use_exposure = false;
break;
case PASS_AOV_COLOR:
pass_info.num_components = 3;
break;
case PASS_AOV_VALUE:
pass_info.num_components = 1;
break;
case PASS_BAKE_PRIMITIVE:
case PASS_BAKE_DIFFERENTIAL:
pass_info.num_components = 4;
pass_info.use_exposure = false;
pass_info.use_filter = false;
break;
case PASS_CATEGORY_LIGHT_END:
case PASS_CATEGORY_DATA_END:
case PASS_CATEGORY_BAKE_END:
case PASS_NUM:
LOG(DFATAL) << "Unexpected pass type is used " << type;
pass_info.num_components = 0;
break;
}
return pass_info;
}
bool Pass::contains(const vector<Pass *> &passes, PassType type)
{
for (const Pass *pass : passes) {
if (pass->get_type() != type) {
continue;
}
return true;
}
return false;
}
const Pass *Pass::find(const vector<Pass *> &passes, const string &name)
{
for (const Pass *pass : passes) {
if (pass->get_name() == name) {
return pass;
}
}
return nullptr;
}
const Pass *Pass::find(const vector<Pass *> &passes, PassType type, PassMode mode)
{
for (const Pass *pass : passes) {
if (pass->get_type() != type || pass->get_mode() != mode) {
continue;
}
return pass;
}
return nullptr;
}
int Pass::get_offset(const vector<Pass *> &passes, const Pass *pass)
{
int pass_offset = 0;
for (const Pass *current_pass : passes) {
/* Note that pass name is allowed to be empty. This is why we check for type and mode. */
if (current_pass->get_type() == pass->get_type() &&
current_pass->get_mode() == pass->get_mode() &&
current_pass->get_name() == pass->get_name()) {
if (current_pass->is_written()) {
return pass_offset;
}
else {
return PASS_UNUSED;
}
}
if (current_pass->is_written()) {
pass_offset += current_pass->get_info().num_components;
}
}
return PASS_UNUSED;
}
std::ostream &operator<<(std::ostream &os, const Pass &pass)
{
os << "type: " << pass_type_as_string(pass.get_type());
os << ", name: \"" << pass.get_name() << "\"";
os << ", mode: " << pass.get_mode();
os << ", is_written: " << string_from_bool(pass.is_written());
return os;
}
CCL_NAMESPACE_END