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/blender/shader.cpp')
-rw-r--r--intern/cycles/blender/shader.cpp256
1 files changed, 233 insertions, 23 deletions
diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp
index 211659ee245..d749686d449 100644
--- a/intern/cycles/blender/shader.cpp
+++ b/intern/cycles/blender/shader.cpp
@@ -22,6 +22,8 @@
#include "util/string.h"
#include "util/task.h"
+#include "BKE_duplilist.h"
+
CCL_NAMESPACE_BEGIN
typedef map<void *, ShaderInput *> PtrInputMap;
@@ -103,6 +105,7 @@ static ImageAlphaType get_image_alpha_type(BL::Image &b_image)
static const string_view object_attr_prefix("\x01object:");
static const string_view instancer_attr_prefix("\x01instancer:");
+static const string_view view_layer_attr_prefix("\x01layer:");
static ustring blender_attribute_name_add_type(const string &name, BlenderAttributeType type)
{
@@ -111,6 +114,8 @@ static ustring blender_attribute_name_add_type(const string &name, BlenderAttrib
return ustring::concat(object_attr_prefix, name);
case BL::ShaderNodeAttribute::attribute_type_INSTANCER:
return ustring::concat(instancer_attr_prefix, name);
+ case BL::ShaderNodeAttribute::attribute_type_VIEW_LAYER:
+ return ustring::concat(view_layer_attr_prefix, name);
default:
return ustring(name);
}
@@ -130,6 +135,11 @@ BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_r
return BL::ShaderNodeAttribute::attribute_type_INSTANCER;
}
+ if (sname.substr(0, view_layer_attr_prefix.size()) == view_layer_attr_prefix) {
+ *r_real_name = sname.substr(view_layer_attr_prefix.size());
+ return BL::ShaderNodeAttribute::attribute_type_VIEW_LAYER;
+ }
+
return BL::ShaderNodeAttribute::attribute_type_GEOMETRY;
}
@@ -205,7 +215,9 @@ static void set_default_value(ShaderInput *input,
}
case SocketType::INT: {
if (b_sock.type() == BL::NodeSocket::type_BOOLEAN) {
- node->set(socket, get_boolean(b_sock.ptr, "default_value"));
+ /* Make sure to call the int overload of set() since this is an integer socket as far as
+ * Cycles is concerned. */
+ node->set(socket, get_boolean(b_sock.ptr, "default_value") ? 1 : 0);
}
else {
node->set(socket, get_int(b_sock.ptr, "default_value"));
@@ -248,6 +260,13 @@ static void get_tex_mapping(TextureNode *mapping, BL::TexMapping &b_mapping)
mapping->set_tex_mapping_z_mapping((TextureMapping::Mapping)b_mapping.mapping_z());
}
+static bool is_image_animated(BL::Image::source_enum b_image_source, BL::ImageUser &b_image_user)
+{
+ return (b_image_source == BL::Image::source_MOVIE ||
+ b_image_source == BL::Image::source_SEQUENCE) &&
+ b_image_user.use_auto_refresh();
+}
+
static ShaderNode *add_node(Scene *scene,
BL::RenderEngine &b_engine,
BL::BlendData &b_data,
@@ -343,6 +362,33 @@ static ShaderNode *add_node(Scene *scene,
mix->set_use_clamp(b_mix_node.use_clamp());
node = mix;
}
+ else if (b_node.is_a(&RNA_ShaderNodeMix)) {
+ BL::ShaderNodeMix b_mix_node(b_node);
+ if (b_mix_node.data_type() == BL::ShaderNodeMix::data_type_VECTOR) {
+ if (b_mix_node.factor_mode() == BL::ShaderNodeMix::factor_mode_UNIFORM) {
+ MixVectorNode *mix_node = graph->create_node<MixVectorNode>();
+ mix_node->set_use_clamp(b_mix_node.clamp_factor());
+ node = mix_node;
+ }
+ else {
+ MixVectorNonUniformNode *mix_node = graph->create_node<MixVectorNonUniformNode>();
+ mix_node->set_use_clamp(b_mix_node.clamp_factor());
+ node = mix_node;
+ }
+ }
+ else if (b_mix_node.data_type() == BL::ShaderNodeMix::data_type_RGBA) {
+ MixColorNode *mix_node = graph->create_node<MixColorNode>();
+ mix_node->set_blend_type((NodeMix)b_mix_node.blend_type());
+ mix_node->set_use_clamp(b_mix_node.clamp_factor());
+ mix_node->set_use_clamp_result(b_mix_node.clamp_result());
+ node = mix_node;
+ }
+ else {
+ MixFloatNode *mix_node = graph->create_node<MixFloatNode>();
+ mix_node->set_use_clamp(b_mix_node.clamp_factor());
+ node = mix_node;
+ }
+ }
else if (b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
node = graph->create_node<SeparateRGBNode>();
}
@@ -751,10 +797,11 @@ static ShaderNode *add_node(Scene *scene,
get_tex_mapping(image, b_texture_mapping);
if (b_image) {
+ BL::Image::source_enum b_image_source = b_image.source();
PointerRNA colorspace_ptr = b_image.colorspace_settings().ptr;
image->set_colorspace(ustring(get_enum_identifier(colorspace_ptr, "name")));
- image->set_animated(b_image_node.image_user().use_auto_refresh());
+ image->set_animated(is_image_animated(b_image_source, b_image_user));
image->set_alpha_type(get_image_alpha_type(b_image));
array<int> tiles;
@@ -766,9 +813,9 @@ static ShaderNode *add_node(Scene *scene,
/* builtin images will use callback-based reading because
* they could only be loaded correct from blender side
*/
- bool is_builtin = b_image.packed_file() || b_image.source() == BL::Image::source_GENERATED ||
- b_image.source() == BL::Image::source_MOVIE ||
- (b_engine.is_preview() && b_image.source() != BL::Image::source_SEQUENCE);
+ bool is_builtin = b_image.packed_file() || b_image_source == BL::Image::source_GENERATED ||
+ b_image_source == BL::Image::source_MOVIE ||
+ (b_engine.is_preview() && b_image_source != BL::Image::source_SEQUENCE);
if (is_builtin) {
/* for builtin images we're using image datablock name to find an image to
@@ -779,7 +826,7 @@ static ShaderNode *add_node(Scene *scene,
*/
int scene_frame = b_scene.frame_current();
int image_frame = image_user_frame_number(b_image_user, b_image, scene_frame);
- if (b_image.source() != BL::Image::source_TILED) {
+ if (b_image_source != BL::Image::source_TILED) {
image->handle = scene->image_manager->add_image(
new BlenderImageLoader(b_image, image_frame, 0, b_engine.is_preview()),
image->image_params());
@@ -797,7 +844,7 @@ static ShaderNode *add_node(Scene *scene,
}
else {
ustring filename = ustring(
- image_user_file_path(b_image_user, b_image, b_scene.frame_current()));
+ image_user_file_path(b_data, b_image_user, b_image, b_scene.frame_current()));
image->set_filename(filename);
}
}
@@ -815,15 +862,15 @@ static ShaderNode *add_node(Scene *scene,
get_tex_mapping(env, b_texture_mapping);
if (b_image) {
+ BL::Image::source_enum b_image_source = b_image.source();
PointerRNA colorspace_ptr = b_image.colorspace_settings().ptr;
env->set_colorspace(ustring(get_enum_identifier(colorspace_ptr, "name")));
-
- env->set_animated(b_env_node.image_user().use_auto_refresh());
+ env->set_animated(is_image_animated(b_image_source, b_image_user));
env->set_alpha_type(get_image_alpha_type(b_image));
- bool is_builtin = b_image.packed_file() || b_image.source() == BL::Image::source_GENERATED ||
- b_image.source() == BL::Image::source_MOVIE ||
- (b_engine.is_preview() && b_image.source() != BL::Image::source_SEQUENCE);
+ bool is_builtin = b_image.packed_file() || b_image_source == BL::Image::source_GENERATED ||
+ b_image_source == BL::Image::source_MOVIE ||
+ (b_engine.is_preview() && b_image_source != BL::Image::source_SEQUENCE);
if (is_builtin) {
int scene_frame = b_scene.frame_current();
@@ -834,7 +881,7 @@ static ShaderNode *add_node(Scene *scene,
}
else {
env->set_filename(
- ustring(image_user_file_path(b_image_user, b_image, b_scene.frame_current())));
+ ustring(image_user_file_path(b_data, b_image_user, b_image, b_scene.frame_current())));
}
}
node = env;
@@ -931,8 +978,22 @@ static ShaderNode *add_node(Scene *scene,
sky->set_sun_disc(b_sky_node.sun_disc());
sky->set_sun_size(b_sky_node.sun_size());
sky->set_sun_intensity(b_sky_node.sun_intensity());
- sky->set_sun_elevation(b_sky_node.sun_elevation());
- sky->set_sun_rotation(b_sky_node.sun_rotation());
+ /* Patch sun position to be able to animate daylight cycle while keeping the shading code
+ * simple. */
+ float sun_rotation = b_sky_node.sun_rotation();
+ /* Wrap into [-2PI..2PI] range. */
+ float sun_elevation = fmodf(b_sky_node.sun_elevation(), M_2PI_F);
+ /* Wrap into [-PI..PI] range. */
+ if (fabsf(sun_elevation) >= M_PI_F) {
+ sun_elevation -= copysignf(2.0f, sun_elevation) * M_PI_F;
+ }
+ /* Wrap into [-PI/2..PI/2] range while keeping the same absolute position. */
+ if (sun_elevation >= M_PI_2_F || sun_elevation <= -M_PI_2_F) {
+ sun_elevation = copysignf(M_PI_F, sun_elevation) - sun_elevation;
+ sun_rotation += M_PI_F;
+ }
+ sky->set_sun_elevation(sun_elevation);
+ sky->set_sun_rotation(sun_rotation);
sky->set_altitude(b_sky_node.altitude());
sky->set_air_density(b_sky_node.air_density());
sky->set_dust_density(b_sky_node.dust_density());
@@ -1053,7 +1114,9 @@ static bool node_use_modified_socket_name(ShaderNode *node)
return true;
}
-static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::NodeSocket &b_socket)
+static ShaderInput *node_find_input_by_name(BL::Node b_node,
+ ShaderNode *node,
+ BL::NodeSocket &b_socket)
{
string name = b_socket.identifier();
ShaderInput *input = node->input(name.c_str());
@@ -1063,6 +1126,35 @@ static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::NodeSocket &b_
if (string_startswith(name, "Shader")) {
string_replace(name, "Shader", "Closure");
}
+
+ /* Map mix node internal name for shader. */
+ if (b_node.is_a(&RNA_ShaderNodeMix)) {
+ if (string_endswith(name, "Factor_Float")) {
+ string_replace(name, "Factor_Float", "Factor");
+ }
+ else if (string_endswith(name, "Factor_Vector")) {
+ string_replace(name, "Factor_Vector", "Factor");
+ }
+ else if (string_endswith(name, "A_Float")) {
+ string_replace(name, "A_Float", "A");
+ }
+ else if (string_endswith(name, "B_Float")) {
+ string_replace(name, "B_Float", "B");
+ }
+ else if (string_endswith(name, "A_Color")) {
+ string_replace(name, "A_Color", "A");
+ }
+ else if (string_endswith(name, "B_Color")) {
+ string_replace(name, "B_Color", "B");
+ }
+ else if (string_endswith(name, "A_Vector")) {
+ string_replace(name, "A_Vector", "A");
+ }
+ else if (string_endswith(name, "B_Vector")) {
+ string_replace(name, "B_Vector", "B");
+ }
+ }
+
input = node->input(name.c_str());
if (!input) {
@@ -1092,7 +1184,9 @@ static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::NodeSocket &b_
return input;
}
-static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::NodeSocket &b_socket)
+static ShaderOutput *node_find_output_by_name(BL::Node b_node,
+ ShaderNode *node,
+ BL::NodeSocket &b_socket)
{
string name = b_socket.identifier();
ShaderOutput *output = node->output(name.c_str());
@@ -1103,6 +1197,21 @@ static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::NodeSocket &
name = "Closure";
output = node->output(name.c_str());
}
+ /* Map internal name for shader. */
+ if (b_node.is_a(&RNA_ShaderNodeMix)) {
+ if (string_endswith(name, "Result_Float")) {
+ string_replace(name, "Result_Float", "Result");
+ output = node->output(name.c_str());
+ }
+ else if (string_endswith(name, "Result_Color")) {
+ string_replace(name, "Result_Color", "Result");
+ output = node->output(name.c_str());
+ }
+ else if (string_endswith(name, "Result_Vector")) {
+ string_replace(name, "Result_Vector", "Result");
+ output = node->output(name.c_str());
+ }
+ }
}
return output;
@@ -1248,7 +1357,11 @@ static void add_nodes(Scene *scene,
if (node) {
/* map node sockets for linking */
for (BL::NodeSocket &b_input : b_node.inputs) {
- ShaderInput *input = node_find_input_by_name(node, b_input);
+ if (b_input.is_unavailable()) {
+ /* Skip unavailable sockets. */
+ continue;
+ }
+ ShaderInput *input = node_find_input_by_name(b_node, node, b_input);
if (!input) {
/* XXX should not happen, report error? */
continue;
@@ -1258,7 +1371,11 @@ static void add_nodes(Scene *scene,
set_default_value(input, b_input, b_data, b_ntree);
}
for (BL::NodeSocket &b_output : b_node.outputs) {
- ShaderOutput *output = node_find_output_by_name(node, b_output);
+ if (b_output.is_unavailable()) {
+ /* Skip unavailable sockets. */
+ continue;
+ }
+ ShaderOutput *output = node_find_output_by_name(b_node, node, b_output);
if (!output) {
/* XXX should not happen, report error? */
continue;
@@ -1318,6 +1435,89 @@ static void add_nodes(Scene *scene,
empty_proxy_map);
}
+/* Look up and constant fold all references to View Layer attributes. */
+void BlenderSync::resolve_view_layer_attributes(Shader *shader,
+ ShaderGraph *graph,
+ BL::Depsgraph &b_depsgraph)
+{
+ bool updated = false;
+
+ foreach (ShaderNode *node, graph->nodes) {
+ if (node->is_a(AttributeNode::node_type)) {
+ AttributeNode *attr_node = static_cast<AttributeNode *>(node);
+
+ std::string real_name;
+ BlenderAttributeType type = blender_attribute_name_split_type(attr_node->get_attribute(),
+ &real_name);
+
+ if (type == BL::ShaderNodeAttribute::attribute_type_VIEW_LAYER) {
+ /* Look up the value. */
+ BL::ViewLayer b_layer = b_depsgraph.view_layer_eval();
+ BL::Scene b_scene = b_depsgraph.scene_eval();
+ float4 value;
+
+ BKE_view_layer_find_rgba_attribute((::Scene *)b_scene.ptr.data,
+ (::ViewLayer *)b_layer.ptr.data,
+ real_name.c_str(),
+ &value.x);
+
+ /* Replace all outgoing links, using appropriate output types. */
+ float val_avg = (value.x + value.y + value.z) / 3.0f;
+
+ foreach (ShaderOutput *output, node->outputs) {
+ float val_float;
+ float3 val_float3;
+
+ if (output->type() == SocketType::FLOAT) {
+ val_float = (output->name() == "Alpha") ? value.w : val_avg;
+ val_float3 = make_float3(val_float);
+ }
+ else {
+ val_float = val_avg;
+ val_float3 = float4_to_float3(value);
+ }
+
+ foreach (ShaderInput *sock, output->links) {
+ if (sock->type() == SocketType::FLOAT) {
+ sock->set(val_float);
+ }
+ else if (SocketType::is_float3(sock->type())) {
+ sock->set(val_float3);
+ }
+
+ sock->constant_folded_in = true;
+ }
+
+ graph->disconnect(output);
+ }
+
+ /* Clear the attribute name to avoid further attempts to look up. */
+ attr_node->set_attribute(ustring());
+ updated = true;
+ }
+ }
+ }
+
+ if (updated) {
+ shader_map.set_flag(shader, SHADER_WITH_LAYER_ATTRS);
+ }
+ else {
+ shader_map.clear_flag(shader, SHADER_WITH_LAYER_ATTRS);
+ }
+}
+
+bool BlenderSync::scene_attr_needs_recalc(Shader *shader, BL::Depsgraph &b_depsgraph)
+{
+ if (shader && shader_map.test_flag(shader, SHADER_WITH_LAYER_ATTRS)) {
+ BL::Scene scene = b_depsgraph.scene_eval();
+
+ return shader_map.check_recalc(scene) || shader_map.check_recalc(scene.world()) ||
+ shader_map.check_recalc(scene.camera());
+ }
+
+ return false;
+}
+
/* Sync Materials */
void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
@@ -1336,7 +1536,8 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
- if (shader_map.add_or_update(&shader, b_mat) || update_all) {
+ if (shader_map.add_or_update(&shader, b_mat) || update_all ||
+ scene_attr_needs_recalc(shader, b_depsgraph)) {
ShaderGraph *graph = new ShaderGraph();
shader->name = b_mat.name().c_str();
@@ -1357,6 +1558,8 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
graph->connect(diffuse->output("BSDF"), out->input("Surface"));
}
+ resolve_view_layer_attributes(shader, graph, b_depsgraph);
+
/* settings */
PointerRNA cmat = RNA_pointer_get(&b_mat.ptr, "cycles");
shader->set_use_mis(get_boolean(cmat, "sample_as_light"));
@@ -1413,9 +1616,11 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
BlenderViewportParameters new_viewport_parameters(b_v3d, use_developer_ui);
+ Shader *shader = scene->default_background;
+
if (world_recalc || update_all || b_world.ptr.data != world_map ||
- viewport_parameters.shader_modified(new_viewport_parameters)) {
- Shader *shader = scene->default_background;
+ viewport_parameters.shader_modified(new_viewport_parameters) ||
+ scene_attr_needs_recalc(shader, b_depsgraph)) {
ShaderGraph *graph = new ShaderGraph();
/* create nodes */
@@ -1513,6 +1718,8 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
background->set_visibility(visibility);
}
+ resolve_view_layer_attributes(shader, graph, b_depsgraph);
+
shader->set_graph(graph);
shader->tag_update(scene);
}
@@ -1579,7 +1786,8 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
- if (shader_map.add_or_update(&shader, b_light) || update_all) {
+ if (shader_map.add_or_update(&shader, b_light) || update_all ||
+ scene_attr_needs_recalc(shader, b_depsgraph)) {
ShaderGraph *graph = new ShaderGraph();
/* create nodes */
@@ -1600,6 +1808,8 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
graph->connect(emission->output("Emission"), out->input("Surface"));
}
+ resolve_view_layer_attributes(shader, graph, b_depsgraph);
+
shader->set_graph(graph);
shader->tag_update(scene);
}