2011-04-27 11:58:34 +00:00
|
|
|
/*
|
2013-08-18 14:16:15 +00:00
|
|
|
* Copyright 2011-2013 Blender Foundation
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* 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
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* 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
|
2014-12-25 02:50:24 +01:00
|
|
|
* limitations under the License.
|
2011-04-27 11:58:34 +00:00
|
|
|
*/
|
|
|
|
|
|
Cycles: Make all #include statements relative to cycles source directory
The idea is to make include statements more explicit and obvious where the
file is coming from, additionally reducing chance of wrong header being
picked up.
For example, it was not obvious whether bvh.h was refferring to builder
or traversal, whenter node.h is a generic graph node or a shader node
and cases like that.
Surely this might look obvious for the active developers, but after some
time of not touching the code it becomes less obvious where file is coming
from.
This was briefly mentioned in T50824 and seems @brecht is fine with such
explicitness, but need to agree with all active developers before committing
this.
Please note that this patch is lacking changes related on GPU/OpenCL
support. This will be solved if/when we all agree this is a good idea to move
forward.
Reviewers: brecht, lukasstockner97, maiself, nirved, dingto, juicyfruit, swerner
Reviewed By: lukasstockner97, maiself, nirved, dingto
Subscribers: brecht
Differential Revision: https://developer.blender.org/D2586
2017-03-28 20:39:14 +02:00
|
|
|
#include "render/background.h"
|
|
|
|
|
#include "render/graph.h"
|
|
|
|
|
#include "render/light.h"
|
|
|
|
|
#include "render/nodes.h"
|
|
|
|
|
#include "render/osl.h"
|
|
|
|
|
#include "render/scene.h"
|
|
|
|
|
#include "render/shader.h"
|
2011-04-27 11:58:34 +00:00
|
|
|
|
Cycles: Make all #include statements relative to cycles source directory
The idea is to make include statements more explicit and obvious where the
file is coming from, additionally reducing chance of wrong header being
picked up.
For example, it was not obvious whether bvh.h was refferring to builder
or traversal, whenter node.h is a generic graph node or a shader node
and cases like that.
Surely this might look obvious for the active developers, but after some
time of not touching the code it becomes less obvious where file is coming
from.
This was briefly mentioned in T50824 and seems @brecht is fine with such
explicitness, but need to agree with all active developers before committing
this.
Please note that this patch is lacking changes related on GPU/OpenCL
support. This will be solved if/when we all agree this is a good idea to move
forward.
Reviewers: brecht, lukasstockner97, maiself, nirved, dingto, juicyfruit, swerner
Reviewed By: lukasstockner97, maiself, nirved, dingto
Subscribers: brecht
Differential Revision: https://developer.blender.org/D2586
2017-03-28 20:39:14 +02:00
|
|
|
#include "blender/blender_texture.h"
|
|
|
|
|
#include "blender/blender_sync.h"
|
|
|
|
|
#include "blender/blender_util.h"
|
2011-04-27 11:58:34 +00:00
|
|
|
|
Cycles: Make all #include statements relative to cycles source directory
The idea is to make include statements more explicit and obvious where the
file is coming from, additionally reducing chance of wrong header being
picked up.
For example, it was not obvious whether bvh.h was refferring to builder
or traversal, whenter node.h is a generic graph node or a shader node
and cases like that.
Surely this might look obvious for the active developers, but after some
time of not touching the code it becomes less obvious where file is coming
from.
This was briefly mentioned in T50824 and seems @brecht is fine with such
explicitness, but need to agree with all active developers before committing
this.
Please note that this patch is lacking changes related on GPU/OpenCL
support. This will be solved if/when we all agree this is a good idea to move
forward.
Reviewers: brecht, lukasstockner97, maiself, nirved, dingto, juicyfruit, swerner
Reviewed By: lukasstockner97, maiself, nirved, dingto
Subscribers: brecht
Differential Revision: https://developer.blender.org/D2586
2017-03-28 20:39:14 +02:00
|
|
|
#include "util/util_debug.h"
|
2017-04-04 13:36:58 +02:00
|
|
|
#include "util/util_foreach.h"
|
Cycles: Make all #include statements relative to cycles source directory
The idea is to make include statements more explicit and obvious where the
file is coming from, additionally reducing chance of wrong header being
picked up.
For example, it was not obvious whether bvh.h was refferring to builder
or traversal, whenter node.h is a generic graph node or a shader node
and cases like that.
Surely this might look obvious for the active developers, but after some
time of not touching the code it becomes less obvious where file is coming
from.
This was briefly mentioned in T50824 and seems @brecht is fine with such
explicitness, but need to agree with all active developers before committing
this.
Please note that this patch is lacking changes related on GPU/OpenCL
support. This will be solved if/when we all agree this is a good idea to move
forward.
Reviewers: brecht, lukasstockner97, maiself, nirved, dingto, juicyfruit, swerner
Reviewed By: lukasstockner97, maiself, nirved, dingto
Subscribers: brecht
Differential Revision: https://developer.blender.org/D2586
2017-03-28 20:39:14 +02:00
|
|
|
#include "util/util_string.h"
|
2017-04-04 13:36:58 +02:00
|
|
|
#include "util/util_set.h"
|
Cycles: Make all #include statements relative to cycles source directory
The idea is to make include statements more explicit and obvious where the
file is coming from, additionally reducing chance of wrong header being
picked up.
For example, it was not obvious whether bvh.h was refferring to builder
or traversal, whenter node.h is a generic graph node or a shader node
and cases like that.
Surely this might look obvious for the active developers, but after some
time of not touching the code it becomes less obvious where file is coming
from.
This was briefly mentioned in T50824 and seems @brecht is fine with such
explicitness, but need to agree with all active developers before committing
this.
Please note that this patch is lacking changes related on GPU/OpenCL
support. This will be solved if/when we all agree this is a good idea to move
forward.
Reviewers: brecht, lukasstockner97, maiself, nirved, dingto, juicyfruit, swerner
Reviewed By: lukasstockner97, maiself, nirved, dingto
Subscribers: brecht
Differential Revision: https://developer.blender.org/D2586
2017-03-28 20:39:14 +02:00
|
|
|
#include "util/util_task.h"
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
typedef map<void*, ShaderInput*> PtrInputMap;
|
|
|
|
|
typedef map<void*, ShaderOutput*> PtrOutputMap;
|
2016-10-24 12:31:11 +02:00
|
|
|
typedef map<string, ConvertNode*> ProxyMap;
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
|
/* Find */
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
void BlenderSync::find_shader(BL::ID& id,
|
2016-05-14 14:50:03 +02:00
|
|
|
vector<Shader*>& used_shaders,
|
|
|
|
|
Shader *default_shader)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2016-05-14 14:50:03 +02:00
|
|
|
Shader *shader = (id)? shader_map.find(id): default_shader;
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2016-05-14 14:50:03 +02:00
|
|
|
used_shaders.push_back(shader);
|
|
|
|
|
shader->tag_used(scene);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
2016-02-10 15:09:45 +01:00
|
|
|
/* RNA translation utilities */
|
|
|
|
|
|
|
|
|
|
static VolumeSampling get_volume_sampling(PointerRNA& ptr)
|
|
|
|
|
{
|
|
|
|
|
return (VolumeSampling)get_enum(ptr,
|
|
|
|
|
"volume_sampling",
|
|
|
|
|
VOLUME_NUM_SAMPLING,
|
|
|
|
|
VOLUME_SAMPLING_DISTANCE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static VolumeInterpolation get_volume_interpolation(PointerRNA& ptr)
|
|
|
|
|
{
|
|
|
|
|
return (VolumeInterpolation)get_enum(ptr,
|
|
|
|
|
"volume_interpolation",
|
|
|
|
|
VOLUME_NUM_INTERPOLATION,
|
|
|
|
|
VOLUME_INTERPOLATION_LINEAR);
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-02 05:13:58 -04:00
|
|
|
static DisplacementMethod get_displacement_method(PointerRNA& ptr)
|
|
|
|
|
{
|
|
|
|
|
return (DisplacementMethod)get_enum(ptr,
|
|
|
|
|
"displacement_method",
|
|
|
|
|
DISPLACE_NUM_METHODS,
|
|
|
|
|
DISPLACE_BUMP);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-10 15:09:45 +01:00
|
|
|
static int validate_enum_value(int value, int num_values, int default_value)
|
|
|
|
|
{
|
|
|
|
|
if(value >= num_values) {
|
|
|
|
|
return default_value;
|
|
|
|
|
}
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename NodeType>
|
2016-02-16 15:32:26 +01:00
|
|
|
static InterpolationType get_image_interpolation(NodeType& b_node)
|
2016-02-10 15:09:45 +01:00
|
|
|
{
|
|
|
|
|
int value = b_node.interpolation();
|
|
|
|
|
return (InterpolationType)validate_enum_value(value,
|
|
|
|
|
INTERPOLATION_NUM_TYPES,
|
|
|
|
|
INTERPOLATION_LINEAR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename NodeType>
|
2016-02-16 15:32:26 +01:00
|
|
|
static ExtensionType get_image_extension(NodeType& b_node)
|
2016-02-10 15:09:45 +01:00
|
|
|
{
|
|
|
|
|
int value = b_node.extension();
|
|
|
|
|
return (ExtensionType)validate_enum_value(value,
|
|
|
|
|
EXTENSION_NUM_TYPES,
|
|
|
|
|
EXTENSION_REPEAT);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* Graph */
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static BL::NodeSocket get_node_output(BL::Node& b_node, const string& name)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
BL::Node::outputs_iterator b_out;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2011-08-21 10:32:15 +00:00
|
|
|
for(b_node.outputs.begin(b_out); b_out != b_node.outputs.end(); ++b_out)
|
2011-04-27 11:58:34 +00:00
|
|
|
if(b_out->name() == name)
|
|
|
|
|
return *b_out;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
assert(0);
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
return *b_out;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static float3 get_node_output_rgba(BL::Node& b_node, const string& name)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::NodeSocket b_sock = get_node_output(b_node, name);
|
|
|
|
|
float value[4];
|
|
|
|
|
RNA_float_get_array(&b_sock.ptr, "default_value", value);
|
|
|
|
|
return make_float3(value[0], value[1], value[2]);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static float get_node_output_value(BL::Node& b_node, const string& name)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::NodeSocket b_sock = get_node_output(b_node, name);
|
|
|
|
|
return RNA_float_get(&b_sock.ptr, "default_value");
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static float3 get_node_output_vector(BL::Node& b_node, const string& name)
|
2012-06-12 07:27:50 +00:00
|
|
|
{
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::NodeSocket b_sock = get_node_output(b_node, name);
|
|
|
|
|
float value[3];
|
|
|
|
|
RNA_float_get_array(&b_sock.ptr, "default_value", value);
|
|
|
|
|
return make_float3(value[0], value[1], value[2]);
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-08 01:32:09 +02:00
|
|
|
static SocketType::Type convert_socket_type(BL::NodeSocket& b_socket)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2015-10-08 19:08:28 +05:00
|
|
|
switch(b_socket.type()) {
|
2013-03-18 16:34:57 +00:00
|
|
|
case BL::NodeSocket::type_VALUE:
|
2016-05-08 01:32:09 +02:00
|
|
|
return SocketType::FLOAT;
|
2013-03-18 16:34:57 +00:00
|
|
|
case BL::NodeSocket::type_INT:
|
2016-05-08 01:32:09 +02:00
|
|
|
return SocketType::INT;
|
2013-03-18 16:34:57 +00:00
|
|
|
case BL::NodeSocket::type_VECTOR:
|
2016-05-08 01:32:09 +02:00
|
|
|
return SocketType::VECTOR;
|
2013-03-18 16:34:57 +00:00
|
|
|
case BL::NodeSocket::type_RGBA:
|
2016-05-08 01:32:09 +02:00
|
|
|
return SocketType::COLOR;
|
2013-03-18 16:34:57 +00:00
|
|
|
case BL::NodeSocket::type_STRING:
|
2016-05-08 01:32:09 +02:00
|
|
|
return SocketType::STRING;
|
2013-03-18 16:34:57 +00:00
|
|
|
case BL::NodeSocket::type_SHADER:
|
2016-05-08 01:32:09 +02:00
|
|
|
return SocketType::CLOSURE;
|
2013-03-18 16:34:57 +00:00
|
|
|
|
|
|
|
|
default:
|
2016-05-08 01:32:09 +02:00
|
|
|
return SocketType::UNDEFINED;
|
2012-06-12 07:27:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static void set_default_value(ShaderInput *input,
|
|
|
|
|
BL::NodeSocket& b_sock,
|
|
|
|
|
BL::BlendData& b_data,
|
|
|
|
|
BL::ID& b_id)
|
2012-06-12 07:27:50 +00:00
|
|
|
{
|
2016-05-07 19:48:28 +02:00
|
|
|
Node *node = input->parent;
|
|
|
|
|
const SocketType& socket = input->socket_type;
|
|
|
|
|
|
2012-06-12 07:27:50 +00:00
|
|
|
/* copy values for non linked inputs */
|
2016-05-08 01:32:09 +02:00
|
|
|
switch(input->type()) {
|
|
|
|
|
case SocketType::FLOAT: {
|
2016-05-07 19:48:28 +02:00
|
|
|
node->set(socket, get_float(b_sock.ptr, "default_value"));
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2016-05-08 01:32:09 +02:00
|
|
|
case SocketType::INT: {
|
2016-05-07 19:48:28 +02:00
|
|
|
node->set(socket, get_int(b_sock.ptr, "default_value"));
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2016-05-08 01:32:09 +02:00
|
|
|
case SocketType::COLOR: {
|
2016-05-07 19:48:28 +02:00
|
|
|
node->set(socket, float4_to_float3(get_float4(b_sock.ptr, "default_value")));
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2016-05-08 01:32:09 +02:00
|
|
|
case SocketType::NORMAL:
|
|
|
|
|
case SocketType::POINT:
|
|
|
|
|
case SocketType::VECTOR: {
|
2016-05-07 19:48:28 +02:00
|
|
|
node->set(socket, get_float3(b_sock.ptr, "default_value"));
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2016-05-08 01:32:09 +02:00
|
|
|
case SocketType::STRING: {
|
2016-05-07 19:48:28 +02:00
|
|
|
node->set(socket, (ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value")));
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2016-05-08 01:32:09 +02:00
|
|
|
default:
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
2012-06-12 07:27:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static void get_tex_mapping(TextureMapping *mapping, BL::TexMapping& b_mapping)
|
2011-11-04 20:58:00 +00:00
|
|
|
{
|
2011-11-21 16:28:19 +00:00
|
|
|
if(!b_mapping)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-04-04 16:11:39 +00:00
|
|
|
mapping->translation = get_float3(b_mapping.translation());
|
2011-11-14 20:39:53 +00:00
|
|
|
mapping->rotation = get_float3(b_mapping.rotation());
|
2011-11-04 20:58:00 +00:00
|
|
|
mapping->scale = get_float3(b_mapping.scale());
|
2013-10-02 17:02:59 +00:00
|
|
|
mapping->type = (TextureMapping::Type)b_mapping.vector_type();
|
2011-11-04 20:58:00 +00:00
|
|
|
|
|
|
|
|
mapping->x_mapping = (TextureMapping::Mapping)b_mapping.mapping_x();
|
|
|
|
|
mapping->y_mapping = (TextureMapping::Mapping)b_mapping.mapping_y();
|
|
|
|
|
mapping->z_mapping = (TextureMapping::Mapping)b_mapping.mapping_z();
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static void get_tex_mapping(TextureMapping *mapping,
|
|
|
|
|
BL::ShaderNodeMapping& b_mapping)
|
2011-11-14 20:39:53 +00:00
|
|
|
{
|
2011-11-21 16:28:19 +00:00
|
|
|
if(!b_mapping)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-04-04 16:11:39 +00:00
|
|
|
mapping->translation = get_float3(b_mapping.translation());
|
2011-11-14 20:39:53 +00:00
|
|
|
mapping->rotation = get_float3(b_mapping.rotation());
|
|
|
|
|
mapping->scale = get_float3(b_mapping.scale());
|
2013-10-02 17:02:59 +00:00
|
|
|
mapping->type = (TextureMapping::Type)b_mapping.vector_type();
|
2012-05-07 20:24:38 +00:00
|
|
|
|
|
|
|
|
mapping->use_minmax = b_mapping.use_min() || b_mapping.use_max();
|
|
|
|
|
|
|
|
|
|
if(b_mapping.use_min())
|
|
|
|
|
mapping->min = get_float3(b_mapping.min());
|
|
|
|
|
if(b_mapping.use_max())
|
|
|
|
|
mapping->max = get_float3(b_mapping.max());
|
2011-11-14 20:39:53 +00:00
|
|
|
}
|
|
|
|
|
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
static ShaderNode *add_node(Scene *scene,
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::RenderEngine& b_engine,
|
|
|
|
|
BL::BlendData& b_data,
|
|
|
|
|
BL::Scene& b_scene,
|
2017-07-21 11:53:13 +02:00
|
|
|
BL::SceneLayer b_scene_layer,
|
2015-11-25 17:38:12 +05:00
|
|
|
const bool background,
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
ShaderGraph *graph,
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::ShaderNodeTree& b_ntree,
|
|
|
|
|
BL::ShaderNode& b_node)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
ShaderNode *node = NULL;
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* existing blender nodes */
|
2015-03-28 00:15:15 +05:00
|
|
|
if(b_node.is_a(&RNA_ShaderNodeRGBCurve)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeRGBCurve b_curve_node(b_node);
|
2015-12-04 20:17:25 +05:00
|
|
|
BL::CurveMapping mapping(b_curve_node.mapping());
|
2013-03-18 16:34:57 +00:00
|
|
|
RGBCurvesNode *curves = new RGBCurvesNode();
|
2015-12-04 20:17:25 +05:00
|
|
|
curvemapping_color_to_array(mapping,
|
|
|
|
|
curves->curves,
|
|
|
|
|
RAMP_TABLE_SIZE,
|
|
|
|
|
true);
|
|
|
|
|
curvemapping_minmax(mapping, true, &curves->min_x, &curves->max_x);
|
2013-03-18 16:34:57 +00:00
|
|
|
node = curves;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
if(b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeVectorCurve b_curve_node(b_node);
|
2015-12-15 16:23:33 +05:00
|
|
|
BL::CurveMapping mapping(b_curve_node.mapping());
|
2013-03-18 16:34:57 +00:00
|
|
|
VectorCurvesNode *curves = new VectorCurvesNode();
|
2015-12-15 16:23:33 +05:00
|
|
|
curvemapping_color_to_array(mapping,
|
|
|
|
|
curves->curves,
|
|
|
|
|
RAMP_TABLE_SIZE,
|
|
|
|
|
false);
|
|
|
|
|
curvemapping_minmax(mapping, false, &curves->min_x, &curves->max_x);
|
2013-03-18 16:34:57 +00:00
|
|
|
node = curves;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeValToRGB)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
RGBRampNode *ramp = new RGBRampNode();
|
|
|
|
|
BL::ShaderNodeValToRGB b_ramp_node(b_node);
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::ColorRamp b_color_ramp(b_ramp_node.color_ramp());
|
2016-05-08 01:54:35 +02:00
|
|
|
colorramp_to_array(b_color_ramp, ramp->ramp, ramp->ramp_alpha, RAMP_TABLE_SIZE);
|
2016-01-30 14:18:29 +01:00
|
|
|
ramp->interpolate = b_color_ramp.interpolation() != BL::ColorRamp::interpolation_CONSTANT;
|
2013-03-18 16:34:57 +00:00
|
|
|
node = ramp;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeRGB)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
ColorNode *color = new ColorNode();
|
|
|
|
|
color->value = get_node_output_rgba(b_node, "Color");
|
|
|
|
|
node = color;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeValue)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
ValueNode *value = new ValueNode();
|
|
|
|
|
value->value = get_node_output_value(b_node, "Value");
|
|
|
|
|
node = value;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeCameraData)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new CameraNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeInvert)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new InvertNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeGamma)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new GammaNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBrightContrast)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new BrightContrastNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeMixRGB)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeMixRGB b_mix_node(b_node);
|
|
|
|
|
MixNode *mix = new MixNode();
|
2016-05-29 16:13:14 +02:00
|
|
|
mix->type = (NodeMix)b_mix_node.blend_type();
|
2014-09-19 12:57:09 +02:00
|
|
|
mix->use_clamp = b_mix_node.use_clamp();
|
2013-03-18 16:34:57 +00:00
|
|
|
node = mix;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new SeparateRGBNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeCombineRGB)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new CombineRGBNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeSeparateHSV)) {
|
2013-07-03 23:46:56 +00:00
|
|
|
node = new SeparateHSVNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeCombineHSV)) {
|
2013-07-03 23:46:56 +00:00
|
|
|
node = new CombineHSVNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeSeparateXYZ)) {
|
2014-06-13 21:44:48 +02:00
|
|
|
node = new SeparateXYZNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeCombineXYZ)) {
|
2014-06-13 21:44:48 +02:00
|
|
|
node = new CombineXYZNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeHueSaturation)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new HSVNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
|
2016-05-29 12:24:47 +02:00
|
|
|
node = new RGBToBWNode();
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeMath)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeMath b_math_node(b_node);
|
|
|
|
|
MathNode *math = new MathNode();
|
2016-05-29 16:13:14 +02:00
|
|
|
math->type = (NodeMath)b_math_node.operation();
|
2014-09-19 12:57:09 +02:00
|
|
|
math->use_clamp = b_math_node.use_clamp();
|
2013-03-18 16:34:57 +00:00
|
|
|
node = math;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeVectorMath)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeVectorMath b_vector_math_node(b_node);
|
|
|
|
|
VectorMathNode *vmath = new VectorMathNode();
|
2016-05-29 16:13:14 +02:00
|
|
|
vmath->type = (NodeVectorMath)b_vector_math_node.operation();
|
2013-03-18 16:34:57 +00:00
|
|
|
node = vmath;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeVectorTransform)) {
|
2013-07-31 21:18:23 +00:00
|
|
|
BL::ShaderNodeVectorTransform b_vector_transform_node(b_node);
|
|
|
|
|
VectorTransformNode *vtransform = new VectorTransformNode();
|
2016-05-29 16:13:14 +02:00
|
|
|
vtransform->type = (NodeVectorTransformType)b_vector_transform_node.vector_type();
|
|
|
|
|
vtransform->convert_from = (NodeVectorTransformConvertSpace)b_vector_transform_node.convert_from();
|
|
|
|
|
vtransform->convert_to = (NodeVectorTransformConvertSpace)b_vector_transform_node.convert_to();
|
2013-07-31 21:18:23 +00:00
|
|
|
node = vtransform;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeNormal)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::Node::outputs_iterator out_it;
|
|
|
|
|
b_node.outputs.begin(out_it);
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
NormalNode *norm = new NormalNode();
|
|
|
|
|
norm->direction = get_node_output_vector(b_node, "Normal");
|
|
|
|
|
node = norm;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeMapping)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeMapping b_mapping_node(b_node);
|
|
|
|
|
MappingNode *mapping = new MappingNode();
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
get_tex_mapping(&mapping->tex_mapping, b_mapping_node);
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
node = mapping;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeFresnel)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new FresnelNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeLayerWeight)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new LayerWeightNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeAddShader)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new AddClosureNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeMixShader)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new MixClosureNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeAttribute)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeAttribute b_attr_node(b_node);
|
|
|
|
|
AttributeNode *attr = new AttributeNode();
|
|
|
|
|
attr->attribute = b_attr_node.attribute_name();
|
|
|
|
|
node = attr;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBackground)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new BackgroundNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeHoldout)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new HoldoutNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
|
2014-06-08 12:16:28 +02:00
|
|
|
BL::ShaderNodeBsdfAnisotropic b_aniso_node(b_node);
|
|
|
|
|
AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode();
|
|
|
|
|
|
2015-10-08 19:08:28 +05:00
|
|
|
switch(b_aniso_node.distribution()) {
|
|
|
|
|
case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
|
2016-05-29 16:13:14 +02:00
|
|
|
aniso->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
|
2015-10-08 19:08:28 +05:00
|
|
|
break;
|
|
|
|
|
case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
|
2016-05-29 16:13:14 +02:00
|
|
|
aniso->distribution = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
|
2015-10-08 19:08:28 +05:00
|
|
|
break;
|
Cycles: Add multi-scattering, energy-conserving GGX as an option to the Glossy, Anisotropic and Glass BSDFs
This commit adds a new distribution to the Glossy, Anisotropic and Glass BSDFs that implements the
multiple-scattering microfacet model described in the paper "Multiple-Scattering Microfacet BSDFs with the Smith Model".
Essentially, the improvement is that unlike classical GGX, which only models single scattering and assumes
the contribution of multiple bounces to be zero, this new model performs a random walk on the microsurface until
the ray leaves it again, which ensures perfect energy conservation.
In practise, this means that the "darkening problem" - GGX materials becoming darker with increasing
roughness - is solved in a physically correct and efficient way.
The downside of this model is that it has no (known) analytic expression for evalation. However, it can be
evaluated stochastically, and although the correct PDF isn't known either, the properties of MIS and the
balance heuristic guarantee an unbiased result at the cost of slightly higher noise.
Reviewers: dingto, #cycles, brecht
Reviewed By: dingto, #cycles, brecht
Subscribers: bliblubli, ace_dragon, gregzaal, brecht, harvester, dingto, marcog, swerner, jtheninja, Blendify, nutel
Differential Revision: https://developer.blender.org/D2002
2016-06-23 22:56:43 +02:00
|
|
|
case BL::ShaderNodeBsdfAnisotropic::distribution_MULTI_GGX:
|
|
|
|
|
aniso->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID;
|
|
|
|
|
break;
|
2015-10-08 19:08:28 +05:00
|
|
|
case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY:
|
2016-05-29 16:13:14 +02:00
|
|
|
aniso->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
|
2015-10-08 19:08:28 +05:00
|
|
|
break;
|
2014-06-08 12:16:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
node = aniso;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new DiffuseBsdfNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) {
|
2013-08-18 14:15:57 +00:00
|
|
|
BL::ShaderNodeSubsurfaceScattering b_subsurface_node(b_node);
|
|
|
|
|
|
|
|
|
|
SubsurfaceScatteringNode *subsurface = new SubsurfaceScatteringNode();
|
|
|
|
|
|
|
|
|
|
switch(b_subsurface_node.falloff()) {
|
2016-02-03 15:00:55 +01:00
|
|
|
case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
|
2016-05-29 16:13:14 +02:00
|
|
|
subsurface->falloff = CLOSURE_BSSRDF_CUBIC_ID;
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
|
|
|
|
case BL::ShaderNodeSubsurfaceScattering::falloff_GAUSSIAN:
|
2016-05-29 16:13:14 +02:00
|
|
|
subsurface->falloff = CLOSURE_BSSRDF_GAUSSIAN_ID;
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
2016-02-04 03:34:49 +05:00
|
|
|
case BL::ShaderNodeSubsurfaceScattering::falloff_BURLEY:
|
2016-05-29 16:13:14 +02:00
|
|
|
subsurface->falloff = CLOSURE_BSSRDF_BURLEY_ID;
|
2016-02-04 03:34:49 +05:00
|
|
|
break;
|
2013-08-18 14:15:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
node = subsurface;
|
2013-04-01 20:26:52 +00:00
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
|
|
|
|
|
GlossyBsdfNode *glossy = new GlossyBsdfNode();
|
|
|
|
|
|
|
|
|
|
switch(b_glossy_node.distribution()) {
|
2016-02-03 15:00:55 +01:00
|
|
|
case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
|
2016-05-29 16:13:14 +02:00
|
|
|
glossy->distribution = CLOSURE_BSDF_REFLECTION_ID;
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
|
|
|
|
case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
|
2016-05-29 16:13:14 +02:00
|
|
|
glossy->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
|
|
|
|
case BL::ShaderNodeBsdfGlossy::distribution_GGX:
|
2016-05-29 16:13:14 +02:00
|
|
|
glossy->distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
|
|
|
|
case BL::ShaderNodeBsdfGlossy::distribution_ASHIKHMIN_SHIRLEY:
|
2016-07-10 16:41:21 +02:00
|
|
|
glossy->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
Cycles: Add multi-scattering, energy-conserving GGX as an option to the Glossy, Anisotropic and Glass BSDFs
This commit adds a new distribution to the Glossy, Anisotropic and Glass BSDFs that implements the
multiple-scattering microfacet model described in the paper "Multiple-Scattering Microfacet BSDFs with the Smith Model".
Essentially, the improvement is that unlike classical GGX, which only models single scattering and assumes
the contribution of multiple bounces to be zero, this new model performs a random walk on the microsurface until
the ray leaves it again, which ensures perfect energy conservation.
In practise, this means that the "darkening problem" - GGX materials becoming darker with increasing
roughness - is solved in a physically correct and efficient way.
The downside of this model is that it has no (known) analytic expression for evalation. However, it can be
evaluated stochastically, and although the correct PDF isn't known either, the properties of MIS and the
balance heuristic guarantee an unbiased result at the cost of slightly higher noise.
Reviewers: dingto, #cycles, brecht
Reviewed By: dingto, #cycles, brecht
Subscribers: bliblubli, ace_dragon, gregzaal, brecht, harvester, dingto, marcog, swerner, jtheninja, Blendify, nutel
Differential Revision: https://developer.blender.org/D2002
2016-06-23 22:56:43 +02:00
|
|
|
case BL::ShaderNodeBsdfGlossy::distribution_MULTI_GGX:
|
|
|
|
|
glossy->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
|
|
|
|
|
break;
|
2012-05-07 20:24:38 +00:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
node = glossy;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfGlass)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeBsdfGlass b_glass_node(b_node);
|
|
|
|
|
GlassBsdfNode *glass = new GlassBsdfNode();
|
|
|
|
|
switch(b_glass_node.distribution()) {
|
2016-02-03 15:00:55 +01:00
|
|
|
case BL::ShaderNodeBsdfGlass::distribution_SHARP:
|
2016-05-29 16:13:14 +02:00
|
|
|
glass->distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
|
|
|
|
case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
|
2016-05-29 16:13:14 +02:00
|
|
|
glass->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID;
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
|
|
|
|
case BL::ShaderNodeBsdfGlass::distribution_GGX:
|
2016-05-29 16:13:14 +02:00
|
|
|
glass->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
|
2016-02-03 15:00:55 +01:00
|
|
|
break;
|
Cycles: Add multi-scattering, energy-conserving GGX as an option to the Glossy, Anisotropic and Glass BSDFs
This commit adds a new distribution to the Glossy, Anisotropic and Glass BSDFs that implements the
multiple-scattering microfacet model described in the paper "Multiple-Scattering Microfacet BSDFs with the Smith Model".
Essentially, the improvement is that unlike classical GGX, which only models single scattering and assumes
the contribution of multiple bounces to be zero, this new model performs a random walk on the microsurface until
the ray leaves it again, which ensures perfect energy conservation.
In practise, this means that the "darkening problem" - GGX materials becoming darker with increasing
roughness - is solved in a physically correct and efficient way.
The downside of this model is that it has no (known) analytic expression for evalation. However, it can be
evaluated stochastically, and although the correct PDF isn't known either, the properties of MIS and the
balance heuristic guarantee an unbiased result at the cost of slightly higher noise.
Reviewers: dingto, #cycles, brecht
Reviewed By: dingto, #cycles, brecht
Subscribers: bliblubli, ace_dragon, gregzaal, brecht, harvester, dingto, marcog, swerner, jtheninja, Blendify, nutel
Differential Revision: https://developer.blender.org/D2002
2016-06-23 22:56:43 +02:00
|
|
|
case BL::ShaderNodeBsdfGlass::distribution_MULTI_GGX:
|
|
|
|
|
glass->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
|
|
|
|
break;
|
2012-12-28 14:21:30 +00:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
node = glass;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
|
|
|
|
|
RefractionBsdfNode *refraction = new RefractionBsdfNode();
|
|
|
|
|
switch(b_refraction_node.distribution()) {
|
|
|
|
|
case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
|
2016-05-29 16:13:14 +02:00
|
|
|
refraction->distribution = CLOSURE_BSDF_REFRACTION_ID;
|
2013-03-18 16:34:57 +00:00
|
|
|
break;
|
|
|
|
|
case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
|
2016-05-29 16:13:14 +02:00
|
|
|
refraction->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
|
2013-03-18 16:34:57 +00:00
|
|
|
break;
|
|
|
|
|
case BL::ShaderNodeBsdfRefraction::distribution_GGX:
|
2016-05-29 16:13:14 +02:00
|
|
|
refraction->distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
2013-03-18 16:34:57 +00:00
|
|
|
break;
|
2012-10-10 15:56:43 +00:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
node = refraction;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfToon)) {
|
2013-05-23 17:45:20 +00:00
|
|
|
BL::ShaderNodeBsdfToon b_toon_node(b_node);
|
|
|
|
|
ToonBsdfNode *toon = new ToonBsdfNode();
|
|
|
|
|
switch(b_toon_node.component()) {
|
|
|
|
|
case BL::ShaderNodeBsdfToon::component_DIFFUSE:
|
2016-05-29 16:13:14 +02:00
|
|
|
toon->component = CLOSURE_BSDF_DIFFUSE_TOON_ID;
|
2013-05-23 17:45:20 +00:00
|
|
|
break;
|
|
|
|
|
case BL::ShaderNodeBsdfToon::component_GLOSSY:
|
2016-05-29 16:13:14 +02:00
|
|
|
toon->component = CLOSURE_BSDF_GLOSSY_TOON_ID;
|
2013-05-23 17:45:20 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
node = toon;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfHair)) {
|
2013-09-15 23:58:00 +00:00
|
|
|
BL::ShaderNodeBsdfHair b_hair_node(b_node);
|
|
|
|
|
HairBsdfNode *hair = new HairBsdfNode();
|
|
|
|
|
switch(b_hair_node.component()) {
|
|
|
|
|
case BL::ShaderNodeBsdfHair::component_Reflection:
|
2016-05-29 16:13:14 +02:00
|
|
|
hair->component = CLOSURE_BSDF_HAIR_REFLECTION_ID;
|
2013-09-15 23:58:00 +00:00
|
|
|
break;
|
|
|
|
|
case BL::ShaderNodeBsdfHair::component_Transmission:
|
2016-05-29 16:13:14 +02:00
|
|
|
hair->component = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
|
2013-09-15 23:58:00 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
node = hair;
|
|
|
|
|
}
|
2017-04-18 11:43:09 +02:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
|
|
|
|
|
BL::ShaderNodeBsdfPrincipled b_principled_node(b_node);
|
|
|
|
|
PrincipledBsdfNode *principled = new PrincipledBsdfNode();
|
|
|
|
|
switch (b_principled_node.distribution()) {
|
|
|
|
|
case BL::ShaderNodeBsdfPrincipled::distribution_GGX:
|
|
|
|
|
principled->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
|
|
|
|
|
break;
|
|
|
|
|
case BL::ShaderNodeBsdfPrincipled::distribution_MULTI_GGX:
|
|
|
|
|
principled->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
node = principled;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new TranslucentBsdfNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new TransparentBsdfNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new VelvetBsdfNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeEmission)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new EmissionNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new AmbientOcclusionNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
|
2013-12-28 01:54:44 +01:00
|
|
|
node = new ScatterVolumeNode();
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
|
2013-12-28 01:54:44 +01:00
|
|
|
node = new AbsorptionVolumeNode();
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new GeometryNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeWireframe)) {
|
2013-05-20 15:58:37 +00:00
|
|
|
BL::ShaderNodeWireframe b_wireframe_node(b_node);
|
|
|
|
|
WireframeNode *wire = new WireframeNode();
|
|
|
|
|
wire->use_pixel_size = b_wireframe_node.use_pixel_size();
|
|
|
|
|
node = wire;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeWavelength)) {
|
2013-06-09 20:46:22 +00:00
|
|
|
node = new WavelengthNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBlackbody)) {
|
2013-07-31 20:56:32 +00:00
|
|
|
node = new BlackbodyNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeLightPath)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new LightPathNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeLightFalloff)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new LightFalloffNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeObjectInfo)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new ObjectInfoNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeParticleInfo)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new ParticleInfoNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeHairInfo)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
node = new HairInfoNode();
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeBump)) {
|
2013-05-10 16:57:17 +00:00
|
|
|
BL::ShaderNodeBump b_bump_node(b_node);
|
|
|
|
|
BumpNode *bump = new BumpNode();
|
|
|
|
|
bump->invert = b_bump_node.invert();
|
|
|
|
|
node = bump;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeScript)) {
|
2012-11-03 14:32:35 +00:00
|
|
|
#ifdef WITH_OSL
|
2013-03-18 16:34:57 +00:00
|
|
|
if(scene->shader_manager->use_osl()) {
|
2012-11-03 14:32:35 +00:00
|
|
|
/* create script node */
|
|
|
|
|
BL::ShaderNodeScript b_script_node(b_node);
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2015-11-25 20:21:06 +05:00
|
|
|
OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager;
|
|
|
|
|
string bytecode_hash = b_script_node.bytecode_hash();
|
|
|
|
|
|
|
|
|
|
if(!bytecode_hash.empty()) {
|
2016-05-29 15:10:34 +02:00
|
|
|
node = manager->osl_node("", bytecode_hash, b_script_node.bytecode());
|
2015-11-25 20:21:06 +05:00
|
|
|
}
|
|
|
|
|
else {
|
2016-05-29 15:10:34 +02:00
|
|
|
string absolute_filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath());
|
|
|
|
|
node = manager->osl_node(absolute_filepath, "");
|
2012-11-03 14:32:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
2015-03-27 19:09:41 +05:00
|
|
|
#else
|
|
|
|
|
(void)b_data;
|
|
|
|
|
(void)b_ntree;
|
2013-03-18 16:34:57 +00:00
|
|
|
#endif
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexImage)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeTexImage b_image_node(b_node);
|
|
|
|
|
BL::Image b_image(b_image_node.image());
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::ImageUser b_image_user(b_image_node.image_user());
|
2013-03-18 16:34:57 +00:00
|
|
|
ImageTextureNode *image = new ImageTextureNode();
|
|
|
|
|
if(b_image) {
|
|
|
|
|
/* 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 ||
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
b_image.source() == BL::Image::source_MOVIE ||
|
2017-02-11 22:24:59 +01:00
|
|
|
(b_engine.is_preview() &&
|
|
|
|
|
b_image.source() != BL::Image::source_SEQUENCE);
|
2013-03-18 16:34:57 +00:00
|
|
|
|
|
|
|
|
if(is_builtin) {
|
|
|
|
|
/* for builtin images we're using image datablock name to find an image to
|
|
|
|
|
* read pixels from later
|
|
|
|
|
*
|
|
|
|
|
* also store frame number as well, so there's no differences in handling
|
|
|
|
|
* builtin names for packed images and movies
|
Packed and generated images support for Cycles
This commit adds support of packed and generated images
for Cycles when using SVM backend. Movies are still not
supported. This changes also doesn't touch OSL which is
much less trivial to adopt for any images which are not
saved to disk.
Implementation details:
- When adding images to Image Manager is now possible
to mark image as builtin. Builtin images will bypass
OIIO loader and will use special loading callbacks.
- Callbacks are set by Blender Session and they're
using C++ RNA interface to obtain needed data (pixels,
dimensions, is_float flag).
- Image Manager assumes file path is used as reference
to a builtin images, but in fact currently image
datablock name is used for reference. This makes it
easy to find an image in BlendData database.
- Added some extra properties to Image RNA:
* channels, which denotes actual number of channels
in ImBuf. This is needed to treat image's pixels
correct (before it wasn't possible because API
used internal number of channels for pixels which
is in fact doesn't correlate with image depth)
* is_float, which is truth if image is stored in
float buffer of ImBuf.
- Implemented string lookup for C++ RNA collections
for cases there's no manual lookup function.
OSL is not supported because it used own image loading
and filtering routines and there's seems to be no API
to feed pre-loaded pixels directly to the library.
Think we'll either need to add some API to support
such kind of feeding or consider OSL does not have
support of packed images at all.
Movies are not supported at this moment because of lack
of RNA API to load specified frame. It's not difficult
to solve, just need to consider what to best here:
* Either write some general python interface for ImBuf
and use it via C++ API, or
* Write a PY API function which will return pixels for
given frame, or
* Use bad-level BKE_* call
Anyway, small steps, further improvements later.
Reviewed by Brecht, thanks!
2013-01-12 10:59:13 +00:00
|
|
|
*/
|
2013-03-18 16:34:57 +00:00
|
|
|
int scene_frame = b_scene.frame_current();
|
2016-01-30 14:18:29 +01:00
|
|
|
int image_frame = image_user_frame_number(b_image_user,
|
|
|
|
|
scene_frame);
|
2013-03-18 16:34:57 +00:00
|
|
|
image->filename = b_image.name() + "@" + string_printf("%d", image_frame);
|
|
|
|
|
image->builtin_data = b_image.ptr.data;
|
2012-11-21 13:00:51 +00:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
else {
|
2016-01-30 14:18:29 +01:00
|
|
|
image->filename = image_user_file_path(b_image_user,
|
|
|
|
|
b_image,
|
|
|
|
|
b_scene.frame_current());
|
2013-03-18 16:34:57 +00:00
|
|
|
image->builtin_data = NULL;
|
2012-11-21 13:00:51 +00:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
|
|
|
|
|
image->animated = b_image_node.image_user().use_auto_refresh();
|
2014-05-07 19:00:15 +02:00
|
|
|
image->use_alpha = b_image.use_alpha();
|
2014-07-18 19:28:33 +06:00
|
|
|
|
|
|
|
|
/* TODO(sergey): Does not work properly when we change builtin type. */
|
2015-03-28 00:15:15 +05:00
|
|
|
if(b_image.is_updated()) {
|
2015-07-21 21:58:19 +02:00
|
|
|
scene->image_manager->tag_reload_image(
|
2016-06-12 17:12:25 +02:00
|
|
|
image->filename.string(),
|
2015-07-21 21:58:19 +02:00
|
|
|
image->builtin_data,
|
2016-02-10 15:09:45 +01:00
|
|
|
get_image_interpolation(b_image_node),
|
2017-01-25 14:02:59 +01:00
|
|
|
get_image_extension(b_image_node),
|
|
|
|
|
image->use_alpha);
|
2014-07-18 19:28:33 +06:00
|
|
|
}
|
2012-11-06 19:59:02 +00:00
|
|
|
}
|
2016-05-29 16:13:14 +02:00
|
|
|
image->color_space = (NodeImageColorSpace)b_image_node.color_space();
|
|
|
|
|
image->projection = (NodeImageProjection)b_image_node.projection();
|
2016-02-10 15:09:45 +01:00
|
|
|
image->interpolation = get_image_interpolation(b_image_node);
|
|
|
|
|
image->extension = get_image_extension(b_image_node);
|
2013-03-18 16:34:57 +00:00
|
|
|
image->projection_blend = b_image_node.projection_blend();
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::TexMapping b_texture_mapping(b_image_node.texture_mapping());
|
|
|
|
|
get_tex_mapping(&image->tex_mapping, b_texture_mapping);
|
2013-03-18 16:34:57 +00:00
|
|
|
node = image;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexEnvironment)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeTexEnvironment b_env_node(b_node);
|
|
|
|
|
BL::Image b_image(b_env_node.image());
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::ImageUser b_image_user(b_env_node.image_user());
|
2013-03-18 16:34:57 +00:00
|
|
|
EnvironmentTextureNode *env = new EnvironmentTextureNode();
|
|
|
|
|
if(b_image) {
|
|
|
|
|
bool is_builtin = b_image.packed_file() ||
|
|
|
|
|
b_image.source() == BL::Image::source_GENERATED ||
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
b_image.source() == BL::Image::source_MOVIE ||
|
2017-02-11 22:24:59 +01:00
|
|
|
(b_engine.is_preview() &&
|
|
|
|
|
b_image.source() != BL::Image::source_SEQUENCE);
|
2013-03-18 16:34:57 +00:00
|
|
|
|
|
|
|
|
if(is_builtin) {
|
|
|
|
|
int scene_frame = b_scene.frame_current();
|
2016-01-30 14:18:29 +01:00
|
|
|
int image_frame = image_user_frame_number(b_image_user,
|
|
|
|
|
scene_frame);
|
2013-03-18 16:34:57 +00:00
|
|
|
env->filename = b_image.name() + "@" + string_printf("%d", image_frame);
|
|
|
|
|
env->builtin_data = b_image.ptr.data;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2016-01-30 14:18:29 +01:00
|
|
|
env->filename = image_user_file_path(b_image_user,
|
|
|
|
|
b_image,
|
|
|
|
|
b_scene.frame_current());
|
2013-03-18 16:34:57 +00:00
|
|
|
env->builtin_data = NULL;
|
|
|
|
|
}
|
2014-05-07 19:00:15 +02:00
|
|
|
|
2016-04-29 10:54:40 +02:00
|
|
|
env->animated = b_env_node.image_user().use_auto_refresh();
|
2014-05-07 19:00:15 +02:00
|
|
|
env->use_alpha = b_image.use_alpha();
|
2014-07-18 19:28:33 +06:00
|
|
|
|
|
|
|
|
/* TODO(sergey): Does not work properly when we change builtin type. */
|
2015-03-28 00:15:15 +05:00
|
|
|
if(b_image.is_updated()) {
|
2016-02-10 15:09:45 +01:00
|
|
|
scene->image_manager->tag_reload_image(
|
2016-06-12 17:12:25 +02:00
|
|
|
env->filename.string(),
|
2016-02-10 15:09:45 +01:00
|
|
|
env->builtin_data,
|
|
|
|
|
get_image_interpolation(b_env_node),
|
2017-01-25 14:02:59 +01:00
|
|
|
EXTENSION_REPEAT,
|
|
|
|
|
env->use_alpha);
|
2014-07-18 19:28:33 +06:00
|
|
|
}
|
2012-11-06 10:18:42 +00:00
|
|
|
}
|
2016-05-29 16:13:14 +02:00
|
|
|
env->color_space = (NodeImageColorSpace)b_env_node.color_space();
|
2016-02-10 15:09:45 +01:00
|
|
|
env->interpolation = get_image_interpolation(b_env_node);
|
2016-05-29 16:13:14 +02:00
|
|
|
env->projection = (NodeEnvironmentProjection)b_env_node.projection();
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::TexMapping b_texture_mapping(b_env_node.texture_mapping());
|
|
|
|
|
get_tex_mapping(&env->tex_mapping, b_texture_mapping);
|
2013-03-18 16:34:57 +00:00
|
|
|
node = env;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexGradient)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeTexGradient b_gradient_node(b_node);
|
|
|
|
|
GradientTextureNode *gradient = new GradientTextureNode();
|
2016-05-29 16:13:14 +02:00
|
|
|
gradient->type = (NodeGradientType)b_gradient_node.gradient_type();
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::TexMapping b_texture_mapping(b_gradient_node.texture_mapping());
|
|
|
|
|
get_tex_mapping(&gradient->tex_mapping, b_texture_mapping);
|
2013-03-18 16:34:57 +00:00
|
|
|
node = gradient;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
|
|
|
|
|
VoronoiTextureNode *voronoi = new VoronoiTextureNode();
|
2016-05-29 16:13:14 +02:00
|
|
|
voronoi->coloring = (NodeVoronoiColoring)b_voronoi_node.coloring();
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::TexMapping b_texture_mapping(b_voronoi_node.texture_mapping());
|
|
|
|
|
get_tex_mapping(&voronoi->tex_mapping, b_texture_mapping);
|
2013-03-18 16:34:57 +00:00
|
|
|
node = voronoi;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexMagic)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeTexMagic b_magic_node(b_node);
|
|
|
|
|
MagicTextureNode *magic = new MagicTextureNode();
|
|
|
|
|
magic->depth = b_magic_node.turbulence_depth();
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::TexMapping b_texture_mapping(b_magic_node.texture_mapping());
|
|
|
|
|
get_tex_mapping(&magic->tex_mapping, b_texture_mapping);
|
2013-03-18 16:34:57 +00:00
|
|
|
node = magic;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexWave)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeTexWave b_wave_node(b_node);
|
|
|
|
|
WaveTextureNode *wave = new WaveTextureNode();
|
2016-05-29 16:13:14 +02:00
|
|
|
wave->type = (NodeWaveType)b_wave_node.wave_type();
|
|
|
|
|
wave->profile = (NodeWaveProfile)b_wave_node.wave_profile();
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::TexMapping b_texture_mapping(b_wave_node.texture_mapping());
|
|
|
|
|
get_tex_mapping(&wave->tex_mapping, b_texture_mapping);
|
2013-03-18 16:34:57 +00:00
|
|
|
node = wave;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexChecker)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeTexChecker b_checker_node(b_node);
|
|
|
|
|
CheckerTextureNode *checker = new CheckerTextureNode();
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::TexMapping b_texture_mapping(b_checker_node.texture_mapping());
|
|
|
|
|
get_tex_mapping(&checker->tex_mapping, b_texture_mapping);
|
2013-03-18 16:34:57 +00:00
|
|
|
node = checker;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexBrick)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeTexBrick b_brick_node(b_node);
|
|
|
|
|
BrickTextureNode *brick = new BrickTextureNode();
|
|
|
|
|
brick->offset = b_brick_node.offset();
|
|
|
|
|
brick->offset_frequency = b_brick_node.offset_frequency();
|
|
|
|
|
brick->squash = b_brick_node.squash();
|
|
|
|
|
brick->squash_frequency = b_brick_node.squash_frequency();
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::TexMapping b_texture_mapping(b_brick_node.texture_mapping());
|
|
|
|
|
get_tex_mapping(&brick->tex_mapping, b_texture_mapping);
|
2013-03-18 16:34:57 +00:00
|
|
|
node = brick;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexNoise)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeTexNoise b_noise_node(b_node);
|
|
|
|
|
NoiseTextureNode *noise = new NoiseTextureNode();
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::TexMapping b_texture_mapping(b_noise_node.texture_mapping());
|
|
|
|
|
get_tex_mapping(&noise->tex_mapping, b_texture_mapping);
|
2013-03-18 16:34:57 +00:00
|
|
|
node = noise;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
|
|
|
|
|
MusgraveTextureNode *musgrave = new MusgraveTextureNode();
|
2016-05-29 16:13:14 +02:00
|
|
|
musgrave->type = (NodeMusgraveType)b_musgrave_node.musgrave_type();
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping());
|
|
|
|
|
get_tex_mapping(&musgrave->tex_mapping, b_texture_mapping);
|
2013-03-18 16:34:57 +00:00
|
|
|
node = musgrave;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexCoord)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
|
|
|
|
|
TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
|
|
|
|
|
tex_coord->from_dupli = b_tex_coord_node.from_dupli();
|
2015-01-21 22:19:31 +05:00
|
|
|
if(b_tex_coord_node.object()) {
|
|
|
|
|
tex_coord->use_transform = true;
|
|
|
|
|
tex_coord->ob_tfm = get_transform(b_tex_coord_node.object().matrix_world());
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
node = tex_coord;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexSky)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeTexSky b_sky_node(b_node);
|
|
|
|
|
SkyTextureNode *sky = new SkyTextureNode();
|
2016-05-29 16:13:14 +02:00
|
|
|
sky->type = (NodeSkyType)b_sky_node.sky_type();
|
2014-02-06 20:53:58 +01:00
|
|
|
sky->sun_direction = normalize(get_float3(b_sky_node.sun_direction()));
|
2013-03-18 16:34:57 +00:00
|
|
|
sky->turbidity = b_sky_node.turbidity();
|
2013-08-28 14:11:28 +00:00
|
|
|
sky->ground_albedo = b_sky_node.ground_albedo();
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::TexMapping b_texture_mapping(b_sky_node.texture_mapping());
|
|
|
|
|
get_tex_mapping(&sky->tex_mapping, b_texture_mapping);
|
2013-03-18 16:34:57 +00:00
|
|
|
node = sky;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeNormalMap)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeNormalMap b_normal_map_node(b_node);
|
|
|
|
|
NormalMapNode *nmap = new NormalMapNode();
|
2016-05-29 16:13:14 +02:00
|
|
|
nmap->space = (NodeNormalMapSpace)b_normal_map_node.space();
|
2013-03-18 16:34:57 +00:00
|
|
|
nmap->attribute = b_normal_map_node.uv_map();
|
|
|
|
|
node = nmap;
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTangent)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::ShaderNodeTangent b_tangent_node(b_node);
|
|
|
|
|
TangentNode *tangent = new TangentNode();
|
2016-05-29 16:13:14 +02:00
|
|
|
tangent->direction_type = (NodeTangentDirectionType)b_tangent_node.direction_type();
|
|
|
|
|
tangent->axis = (NodeTangentAxis)b_tangent_node.axis();
|
2013-03-18 16:34:57 +00:00
|
|
|
tangent->attribute = b_tangent_node.uv_map();
|
|
|
|
|
node = tangent;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeUVMap)) {
|
2014-04-02 11:40:29 +02:00
|
|
|
BL::ShaderNodeUVMap b_uvmap_node(b_node);
|
|
|
|
|
UVMapNode *uvm = new UVMapNode();
|
|
|
|
|
uvm->attribute = b_uvmap_node.uv_map();
|
|
|
|
|
uvm->from_dupli = b_uvmap_node.from_dupli();
|
|
|
|
|
node = uvm;
|
|
|
|
|
}
|
2015-07-18 22:36:09 +02:00
|
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
|
|
|
|
|
BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
|
|
|
|
|
PointDensityTextureNode *point_density = new PointDensityTextureNode();
|
|
|
|
|
point_density->filename = b_point_density_node.name();
|
2016-05-29 16:13:14 +02:00
|
|
|
point_density->space = (NodeTexVoxelSpace)b_point_density_node.space();
|
2016-02-10 15:09:45 +01:00
|
|
|
point_density->interpolation = get_image_interpolation(b_point_density_node);
|
2015-07-18 22:36:09 +02:00
|
|
|
point_density->builtin_data = b_point_density_node.ptr.data;
|
|
|
|
|
|
2016-01-26 12:50:55 +01:00
|
|
|
/* 1 - render settings, 0 - vewport settings. */
|
|
|
|
|
int settings = background ? 1 : 0;
|
2015-07-18 22:36:09 +02:00
|
|
|
|
|
|
|
|
/* TODO(sergey): Use more proper update flag. */
|
|
|
|
|
if(true) {
|
2017-07-21 11:53:13 +02:00
|
|
|
b_point_density_node.cache_point_density(b_scene, b_scene_layer, settings);
|
2015-07-21 21:58:19 +02:00
|
|
|
scene->image_manager->tag_reload_image(
|
2016-05-07 19:48:28 +02:00
|
|
|
point_density->filename.string(),
|
2015-07-21 21:58:19 +02:00
|
|
|
point_density->builtin_data,
|
|
|
|
|
point_density->interpolation,
|
2017-01-25 14:02:59 +01:00
|
|
|
EXTENSION_CLIP,
|
|
|
|
|
true);
|
2015-07-18 22:36:09 +02:00
|
|
|
}
|
|
|
|
|
node = point_density;
|
2016-01-26 12:50:55 +01:00
|
|
|
|
|
|
|
|
/* Transformation form world space to texture space.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: Do this after the texture is cached, this is because getting
|
|
|
|
|
* min/max will need to access this cache.
|
|
|
|
|
*/
|
|
|
|
|
BL::Object b_ob(b_point_density_node.object());
|
|
|
|
|
if(b_ob) {
|
|
|
|
|
float3 loc, size;
|
2017-07-21 11:53:13 +02:00
|
|
|
point_density_texture_space(b_scene, b_scene_layer,
|
2016-01-26 12:50:55 +01:00
|
|
|
b_point_density_node,
|
|
|
|
|
settings,
|
|
|
|
|
loc,
|
|
|
|
|
size);
|
|
|
|
|
point_density->tfm =
|
|
|
|
|
transform_translate(-loc) * transform_scale(size) *
|
|
|
|
|
transform_inverse(get_transform(b_ob.matrix_world()));
|
|
|
|
|
}
|
2015-07-18 22:36:09 +02:00
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2016-08-04 14:48:34 +03:00
|
|
|
if(node) {
|
|
|
|
|
node->name = b_node.name();
|
2011-04-27 11:58:34 +00:00
|
|
|
graph->add(node);
|
2016-08-04 14:48:34 +03:00
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-30 11:21:31 +00:00
|
|
|
static bool node_use_modified_socket_name(ShaderNode *node)
|
|
|
|
|
{
|
2015-03-28 00:15:15 +05:00
|
|
|
if(node->special_type == SHADER_SPECIAL_TYPE_SCRIPT)
|
2013-10-30 11:21:31 +00:00
|
|
|
return false;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-10-30 11:21:31 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static ShaderInput *node_find_input_by_name(ShaderNode *node,
|
|
|
|
|
BL::Node& b_node,
|
|
|
|
|
BL::NodeSocket& b_socket)
|
2011-09-16 13:14:02 +00:00
|
|
|
{
|
2011-10-12 15:45:52 +00:00
|
|
|
string name = b_socket.name();
|
2013-03-18 16:34:57 +00:00
|
|
|
|
2015-03-28 00:15:15 +05:00
|
|
|
if(node_use_modified_socket_name(node)) {
|
2013-10-30 11:21:31 +00:00
|
|
|
BL::Node::inputs_iterator b_input;
|
|
|
|
|
bool found = false;
|
|
|
|
|
int counter = 0, total = 0;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2015-03-28 00:15:15 +05:00
|
|
|
for(b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
|
|
|
|
|
if(b_input->name() == name) {
|
|
|
|
|
if(!found)
|
2013-10-30 11:21:31 +00:00
|
|
|
counter++;
|
|
|
|
|
total++;
|
|
|
|
|
}
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-10-30 11:21:31 +00:00
|
|
|
if(b_input->ptr.data == b_socket.ptr.data)
|
|
|
|
|
found = true;
|
2011-10-12 15:45:52 +00:00
|
|
|
}
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-10-30 11:21:31 +00:00
|
|
|
/* rename if needed */
|
2015-03-28 00:15:15 +05:00
|
|
|
if(name == "Shader")
|
2013-10-30 11:21:31 +00:00
|
|
|
name = "Closure";
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2015-03-28 00:15:15 +05:00
|
|
|
if(total > 1)
|
2013-10-30 11:21:31 +00:00
|
|
|
name = string_printf("%s%d", name.c_str(), counter);
|
2011-09-16 13:14:02 +00:00
|
|
|
}
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
return node->input(name.c_str());
|
|
|
|
|
}
|
2011-09-16 13:14:02 +00:00
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static ShaderOutput *node_find_output_by_name(ShaderNode *node,
|
|
|
|
|
BL::Node& b_node,
|
|
|
|
|
BL::NodeSocket& b_socket)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
|
|
|
|
string name = b_socket.name();
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2015-03-28 00:15:15 +05:00
|
|
|
if(node_use_modified_socket_name(node)) {
|
2013-10-30 11:21:31 +00:00
|
|
|
BL::Node::outputs_iterator b_output;
|
|
|
|
|
bool found = false;
|
|
|
|
|
int counter = 0, total = 0;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2015-03-28 00:15:15 +05:00
|
|
|
for(b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
|
|
|
|
|
if(b_output->name() == name) {
|
|
|
|
|
if(!found)
|
2013-10-30 11:21:31 +00:00
|
|
|
counter++;
|
|
|
|
|
total++;
|
|
|
|
|
}
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-10-30 11:21:31 +00:00
|
|
|
if(b_output->ptr.data == b_socket.ptr.data)
|
|
|
|
|
found = true;
|
2011-10-12 15:45:52 +00:00
|
|
|
}
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-10-30 11:21:31 +00:00
|
|
|
/* rename if needed */
|
2015-03-28 00:15:15 +05:00
|
|
|
if(name == "Shader")
|
2013-10-30 11:21:31 +00:00
|
|
|
name = "Closure";
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2015-03-28 00:15:15 +05:00
|
|
|
if(total > 1)
|
2013-10-30 11:21:31 +00:00
|
|
|
name = string_printf("%s%d", name.c_str(), counter);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
return node->output(name.c_str());
|
2011-09-16 13:14:02 +00:00
|
|
|
}
|
|
|
|
|
|
2017-08-01 18:03:16 +02:00
|
|
|
static BL::ShaderNode find_output_node(BL::ShaderNodeTree& b_ntree)
|
|
|
|
|
{
|
|
|
|
|
BL::ShaderNodeTree::nodes_iterator b_node;
|
|
|
|
|
BL::ShaderNode output_node(PointerRNA_NULL);
|
|
|
|
|
BL::ShaderNode eevee_output_node(PointerRNA_NULL);
|
|
|
|
|
|
|
|
|
|
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
|
|
|
|
|
BL::ShaderNodeOutputMaterial b_output_node(*b_node);
|
|
|
|
|
|
|
|
|
|
if (b_output_node.is_a(&RNA_ShaderNodeOutputMaterial) ||
|
|
|
|
|
b_output_node.is_a(&RNA_ShaderNodeOutputWorld) ||
|
|
|
|
|
b_output_node.is_a(&RNA_ShaderNodeOutputLamp)) {
|
|
|
|
|
/* regular Cycles output node */
|
|
|
|
|
if(b_output_node.is_active_output()) {
|
|
|
|
|
output_node = b_output_node;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if(!output_node.ptr.data) {
|
|
|
|
|
output_node = b_output_node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (b_output_node.is_a(&RNA_ShaderNodeOutputEeveeMaterial)) {
|
|
|
|
|
/* Eevee output used if no Cycles node exists */
|
|
|
|
|
if(b_output_node.is_active_output()) {
|
|
|
|
|
eevee_output_node = b_output_node;
|
|
|
|
|
}
|
|
|
|
|
else if(!eevee_output_node.ptr.data) {
|
|
|
|
|
eevee_output_node = b_output_node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (output_node.ptr.data) ? output_node : eevee_output_node;
|
|
|
|
|
}
|
|
|
|
|
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
static void add_nodes(Scene *scene,
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::RenderEngine& b_engine,
|
|
|
|
|
BL::BlendData& b_data,
|
|
|
|
|
BL::Scene& b_scene,
|
2017-07-21 11:53:13 +02:00
|
|
|
BL::SceneLayer& b_scene_layer,
|
2015-11-25 17:38:12 +05:00
|
|
|
const bool background,
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
ShaderGraph *graph,
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::ShaderNodeTree& b_ntree,
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
const ProxyMap &proxy_input_map,
|
|
|
|
|
const ProxyMap &proxy_output_map)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
/* add nodes */
|
|
|
|
|
BL::ShaderNodeTree::nodes_iterator b_node;
|
2013-03-18 16:34:57 +00:00
|
|
|
PtrInputMap input_map;
|
|
|
|
|
PtrOutputMap output_map;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
BL::Node::inputs_iterator b_input;
|
|
|
|
|
BL::Node::outputs_iterator b_output;
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2014-01-20 20:29:05 +01:00
|
|
|
/* find the node to use for output if there are multiple */
|
2017-08-01 18:03:16 +02:00
|
|
|
BL::ShaderNode output_node = find_output_node(b_ntree);
|
2014-01-20 20:29:05 +01:00
|
|
|
|
|
|
|
|
/* add nodes */
|
2011-08-21 10:32:15 +00:00
|
|
|
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
|
2015-03-28 00:15:15 +05:00
|
|
|
if(b_node->mute() || b_node->is_a(&RNA_NodeReroute)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
/* replace muted node with internal links */
|
|
|
|
|
BL::Node::internal_links_iterator b_link;
|
2015-03-28 00:15:15 +05:00
|
|
|
for(b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) {
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::NodeSocket to_socket(b_link->to_socket());
|
2016-05-08 01:32:09 +02:00
|
|
|
SocketType::Type to_socket_type = convert_socket_type(to_socket);
|
2016-05-02 00:05:16 +02:00
|
|
|
ConvertNode *proxy = new ConvertNode(to_socket_type, to_socket_type, true);
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
|
|
|
|
|
output_map[b_link->to_socket().ptr.data] = proxy->outputs[0];
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
graph->add(proxy);
|
2012-10-24 21:05:44 +00:00
|
|
|
}
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node->is_a(&RNA_ShaderNodeGroup) || b_node->is_a(&RNA_NodeCustomGroup)) {
|
2013-03-20 13:17:35 +00:00
|
|
|
|
2013-06-10 12:19:39 +00:00
|
|
|
BL::ShaderNodeTree b_group_ntree(PointerRNA_NULL);
|
2015-03-28 00:15:15 +05:00
|
|
|
if(b_node->is_a(&RNA_ShaderNodeGroup))
|
2013-06-10 12:19:39 +00:00
|
|
|
b_group_ntree = BL::ShaderNodeTree(((BL::NodeGroup)(*b_node)).node_tree());
|
|
|
|
|
else
|
|
|
|
|
b_group_ntree = BL::ShaderNodeTree(((BL::NodeCustomGroup)(*b_node)).node_tree());
|
2013-04-11 09:16:36 +00:00
|
|
|
ProxyMap group_proxy_input_map, group_proxy_output_map;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-20 13:17:35 +00:00
|
|
|
/* Add a proxy node for each socket
|
|
|
|
|
* Do this even if the node group has no internal tree,
|
|
|
|
|
* so that links have something to connect to and assert won't fail.
|
|
|
|
|
*/
|
2015-10-10 21:54:34 +02:00
|
|
|
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
|
2016-05-08 01:32:09 +02:00
|
|
|
SocketType::Type input_type = convert_socket_type(*b_input);
|
2016-05-02 00:05:16 +02:00
|
|
|
ConvertNode *proxy = new ConvertNode(input_type, input_type, true);
|
2013-03-20 13:17:35 +00:00
|
|
|
graph->add(proxy);
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-20 13:17:35 +00:00
|
|
|
/* register the proxy node for internal binding */
|
2013-04-11 09:16:36 +00:00
|
|
|
group_proxy_input_map[b_input->identifier()] = proxy;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
input_map[b_input->ptr.data] = proxy->inputs[0];
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2015-10-10 21:54:34 +02:00
|
|
|
set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree);
|
2011-12-18 15:34:06 +00:00
|
|
|
}
|
|
|
|
|
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
|
2016-05-08 01:32:09 +02:00
|
|
|
SocketType::Type output_type = convert_socket_type(*b_output);
|
2016-05-02 00:05:16 +02:00
|
|
|
ConvertNode *proxy = new ConvertNode(output_type, output_type, true);
|
2013-03-20 13:17:35 +00:00
|
|
|
graph->add(proxy);
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-20 13:17:35 +00:00
|
|
|
/* register the proxy node for internal binding */
|
2013-04-11 09:16:36 +00:00
|
|
|
group_proxy_output_map[b_output->identifier()] = proxy;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
output_map[b_output->ptr.data] = proxy->outputs[0];
|
|
|
|
|
}
|
2013-03-20 13:17:35 +00:00
|
|
|
|
2015-06-01 18:11:57 +05:00
|
|
|
if(b_group_ntree) {
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
add_nodes(scene,
|
|
|
|
|
b_engine,
|
|
|
|
|
b_data,
|
|
|
|
|
b_scene,
|
2017-07-21 11:53:13 +02:00
|
|
|
b_scene_layer,
|
2015-11-25 17:38:12 +05:00
|
|
|
background,
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
graph,
|
|
|
|
|
b_group_ntree,
|
|
|
|
|
group_proxy_input_map,
|
|
|
|
|
group_proxy_output_map);
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node->is_a(&RNA_NodeGroupInput)) {
|
2013-03-20 13:17:35 +00:00
|
|
|
/* map each socket to a proxy node */
|
2013-03-18 16:34:57 +00:00
|
|
|
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
|
2013-04-11 09:16:36 +00:00
|
|
|
ProxyMap::const_iterator proxy_it = proxy_input_map.find(b_output->identifier());
|
2015-03-28 00:15:15 +05:00
|
|
|
if(proxy_it != proxy_input_map.end()) {
|
2016-05-02 00:05:16 +02:00
|
|
|
ConvertNode *proxy = proxy_it->second;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-20 13:17:35 +00:00
|
|
|
output_map[b_output->ptr.data] = proxy->outputs[0];
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
2015-03-28 00:15:15 +05:00
|
|
|
else if(b_node->is_a(&RNA_NodeGroupOutput)) {
|
2013-03-20 13:17:35 +00:00
|
|
|
BL::NodeGroupOutput b_output_node(*b_node);
|
|
|
|
|
/* only the active group output is used */
|
2015-03-28 00:15:15 +05:00
|
|
|
if(b_output_node.is_active_output()) {
|
2013-03-20 13:17:35 +00:00
|
|
|
/* map each socket to a proxy node */
|
|
|
|
|
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
|
2013-04-11 09:16:36 +00:00
|
|
|
ProxyMap::const_iterator proxy_it = proxy_output_map.find(b_input->identifier());
|
2015-03-28 00:15:15 +05:00
|
|
|
if(proxy_it != proxy_output_map.end()) {
|
2016-05-02 00:05:16 +02:00
|
|
|
ConvertNode *proxy = proxy_it->second;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-20 13:17:35 +00:00
|
|
|
input_map[b_input->ptr.data] = proxy->inputs[0];
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2015-03-27 15:47:55 +05:00
|
|
|
set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree);
|
2013-03-20 13:17:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-12-18 15:34:06 +00:00
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2014-01-20 20:29:05 +01:00
|
|
|
ShaderNode *node = NULL;
|
|
|
|
|
|
2017-08-01 18:03:16 +02:00
|
|
|
if(b_node->ptr.data == output_node.ptr.data) {
|
|
|
|
|
node = graph->output();
|
2014-01-20 20:29:05 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::ShaderNode b_shader_node(*b_node);
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
node = add_node(scene,
|
|
|
|
|
b_engine,
|
|
|
|
|
b_data,
|
|
|
|
|
b_scene,
|
2017-07-21 11:53:13 +02:00
|
|
|
b_scene_layer,
|
2015-11-25 17:38:12 +05:00
|
|
|
background,
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
graph,
|
|
|
|
|
b_ntree,
|
2016-01-30 14:18:29 +01:00
|
|
|
b_shader_node);
|
2014-01-20 20:29:05 +01:00
|
|
|
}
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
if(node) {
|
2013-03-18 16:34:57 +00:00
|
|
|
/* map node sockets for linking */
|
2011-08-21 10:32:15 +00:00
|
|
|
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
|
2013-03-18 16:34:57 +00:00
|
|
|
ShaderInput *input = node_find_input_by_name(node, *b_node, *b_input);
|
2015-03-28 00:15:15 +05:00
|
|
|
if(!input) {
|
2014-06-06 09:25:05 +02:00
|
|
|
/* XXX should not happen, report error? */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
input_map[b_input->ptr.data] = input;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2015-03-27 15:47:55 +05:00
|
|
|
set_default_value(input, *b_input, b_data, b_ntree);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
|
|
|
|
|
ShaderOutput *output = node_find_output_by_name(node, *b_node, *b_output);
|
2015-03-28 00:15:15 +05:00
|
|
|
if(!output) {
|
2014-06-06 09:25:05 +02:00
|
|
|
/* XXX should not happen, report error? */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
output_map[b_output->ptr.data] = output;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* connect nodes */
|
|
|
|
|
BL::NodeTree::links_iterator b_link;
|
|
|
|
|
|
2011-08-21 10:32:15 +00:00
|
|
|
for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
|
2015-03-25 13:46:59 +05:00
|
|
|
/* Ignore invalid links to avoid unwanted cycles created in graph. */
|
|
|
|
|
if(!b_link->is_valid()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
/* get blender link data */
|
|
|
|
|
BL::NodeSocket b_from_sock = b_link->from_socket();
|
|
|
|
|
BL::NodeSocket b_to_sock = b_link->to_socket();
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
ShaderOutput *output = 0;
|
|
|
|
|
ShaderInput *input = 0;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
PtrOutputMap::iterator output_it = output_map.find(b_from_sock.ptr.data);
|
2015-03-28 00:15:15 +05:00
|
|
|
if(output_it != output_map.end())
|
2013-03-18 16:34:57 +00:00
|
|
|
output = output_it->second;
|
|
|
|
|
PtrInputMap::iterator input_it = input_map.find(b_to_sock.ptr.data);
|
2015-03-28 00:15:15 +05:00
|
|
|
if(input_it != input_map.end())
|
2013-03-18 16:34:57 +00:00
|
|
|
input = input_it->second;
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2011-12-28 19:42:08 +00:00
|
|
|
/* either node may be NULL when the node was not exported, typically
|
2012-06-09 17:22:52 +00:00
|
|
|
* because the node type is not supported */
|
2013-03-18 16:34:57 +00:00
|
|
|
if(output && input)
|
2011-12-28 19:42:08 +00:00
|
|
|
graph->connect(output, input);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
static void add_nodes(Scene *scene,
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::RenderEngine& b_engine,
|
|
|
|
|
BL::BlendData& b_data,
|
|
|
|
|
BL::Scene& b_scene,
|
2017-07-21 11:53:13 +02:00
|
|
|
BL::SceneLayer& b_scene_layer,
|
2015-11-25 17:38:12 +05:00
|
|
|
const bool background,
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
ShaderGraph *graph,
|
2016-01-30 14:18:29 +01:00
|
|
|
BL::ShaderNodeTree& b_ntree)
|
2013-04-11 09:16:36 +00:00
|
|
|
{
|
|
|
|
|
static const ProxyMap empty_proxy_map;
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
add_nodes(scene,
|
|
|
|
|
b_engine,
|
|
|
|
|
b_data,
|
|
|
|
|
b_scene,
|
2017-07-21 11:53:13 +02:00
|
|
|
b_scene_layer,
|
2015-11-25 17:38:12 +05:00
|
|
|
background,
|
Cycles: Experiment with making previews more interactive
There were two major problems with the interactivity of material previews:
- Beckmann tables were re-generated on every material tweak.
This is because preview scene is not set to be persistent, so re-triggering
the render leads to the full scene re-sync.
- Images could take rather noticeable time to load with OIIO from the disk
on every tweak.
This patch addressed this two issues in the following way:
- Beckmann tables are now static on CPU memory.
They're couple of hundred kilobytes only, so wouldn't expect this to be
an issue. And they're needed for almost every render anyway.
This actually also makes blackbody table to be static, but it's even smaller
than beckmann table.
Not totally happy with this approach, but others seems to complicate things
quite a bit with all this render engine life time and so..
- For preview rendering all images are considered to be built-in. This means
instead of OIIO which re-loads images on every re-render they're coming
from ImBuf cache which is fully manageable from blender side and unused
images gets freed later.
This would make it impossible to have mipmapping with OSL for now, but we'll
be working on that later anyway and don't think mipmaps are really so crucial
for the material preview.
This seems to be a better alternative to making preview scene persistent,
because of much optimal memory control from blender side.
Reviewers: brecht, juicyfruit, campbellbarton, dingto
Subscribers: eyecandy, venomgfx
Differential Revision: https://developer.blender.org/D1132
2015-02-21 21:55:24 +05:00
|
|
|
graph,
|
|
|
|
|
b_ntree,
|
|
|
|
|
empty_proxy_map,
|
|
|
|
|
empty_proxy_map);
|
2013-04-11 09:16:36 +00:00
|
|
|
}
|
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* Sync Materials */
|
|
|
|
|
|
2012-11-21 13:00:51 +00:00
|
|
|
void BlenderSync::sync_materials(bool update_all)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2016-05-14 14:50:03 +02:00
|
|
|
shader_map.set_default(scene->default_surface);
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2016-12-14 23:47:39 +01:00
|
|
|
TaskPool pool;
|
2017-04-04 13:36:58 +02:00
|
|
|
set<Shader*> updated_shaders;
|
2016-12-14 23:47:39 +01:00
|
|
|
|
Depsgraph: Initial groundwork for copy-on-write support
< Dependency graph Copy-on-Write >
--------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
This is an initial commit of Copy-on-write support added to dependency graph.
Main priority for now: get playback (Alt-A) and all operators (selection,
transform etc) to work with the new concept of clear separation between
evaluated data coming from dependency graph and original data coming from
.blend file (and stored in bmain).
= How does this work? =
The idea is to support Copy-on-Write on the ID level. This means, we duplicate
the whole ID before we cann it's evaluaiton function. This is currently done
in the following way:
- At the depsgraph construction time we create "shallow" copy of the ID
datablock, just so we know it's pointer in memory and can use for function
bindings.
- At the evaluaiton time, the copy of ID get's "expanded" (needs a better
name internally, so it does not conflict with expanding datablocks during
library linking), which means the content of the datablock is being
copied over and all IDs are getting remapped to the copied ones.
Currently we do the whole copy, in the future we will support some tricks
here to prevent duplicating geometry arrays (verts, edges, loops, faces
and polys) when we don't need that.
- Evaluation functions are operating on copied datablocks and never touching
original datablock.
- There are some cases when we need to know non-ID pointers for function
bindings. This mainly applies to scene collections and armatures. The
idea of dealing with this is to "expand" copy-on-write datablock at
the dependency graph build time. This might introduce some slowdown to the
dependency graph construction time, but allows us to have minimal changes
in the code and avoid any hash look-up from evaluation function (one of
the ideas to avoid using pointers as function bindings is to pass name
of layer or a bone to the evaluation function and look up actual data based
on that name).
Currently there is a special function in depsgraph which does such a
synchronization, in the future we might want to make it more generic.
At some point we need to synchronize copy-on-write version of datablock with
the original version. This happens, i.e., when we change active object or
change selection. We don't want any actual evaluation of update flush happening
for such thins, so now we have a special update tag:
DEG_id_tag_update((id, DEG_TAG_COPY_ON_WRITE)
- For the render engines we now have special call for the dependency graph to
give evaluated datablock for the given original one. This isn't fully ideal
but allows to have Cycles viewport render.
This is definitely a subject for further investigation / improvement.
This call will tag copy-on-write component tagged for update without causing
updates to be flushed to any other objects, causing chain reaction of updates.
This tag is handy when selection in the scene changes.
This basically summarizes ideas underneath this commit. The code should be
reasonably documented.
Here is a demo of dependency graph with all copy-on-write stuff in it:
https://developer.blender.org/F635468
= What to expect to (not) work? =
- Only meshes are properly-ish aware of copy-on-write currently, Non-mesh
geometry will probably crash or will not work at all.
- Armatures will need similar depsgraph built-time expansion of the copied
datablock.
- There are some extra tags / relations added, to keep things demo-able but
which are slowing things down for evaluation.
- Edit mode works for until click selection is used (due to the selection
code using EditDerivedMesh created ad-hoc).
- Lots of tools will lack tagging synchronization of copied datablock for
sync with original ID.
= How to move forward? =
There is some tedious work related on going over all the tools, checking
whether they need to work with original or final evaluated object and make
the required changes.
Additionally, there need synchronization tag done in fair amount of tools
and operators as well. For example, currently it's not possible to change
render engine without re-opening the file or forcing dependency graph for
re-build via python console.
There is also now some thoughts required about copying evaluated properties
between objects or from collection to a new object. Perhaps easiest way
would be to move base flag flush to Object ID node and tag new objects for
update instead of doing manual copy.
here is some WIP patch which moves such evaluaiton / flush:
https://developer.blender.org/F635479
Lots of TODOs in the code, with possible optimization.
= How to test? =
This is a feature under heavy development, so obviously it is disabled by
default. The only reason it goes to 2.8 branch is to avoid possible merge
hell.
In order to enable this feature use WITH_DEPSGRAPH_COPY_ON_WRITE CMake
configuration option.
2017-06-14 10:26:24 +02:00
|
|
|
/* material loop */
|
|
|
|
|
BL::BlendData::materials_iterator b_mat_orig;
|
|
|
|
|
for(b_data.materials.begin(b_mat_orig);
|
|
|
|
|
b_mat_orig != b_data.materials.end();
|
|
|
|
|
++b_mat_orig)
|
|
|
|
|
{
|
|
|
|
|
/* TODO(sergey): Iterate over evaluated data rather than using mapping. */
|
|
|
|
|
BL::Material b_mat_(b_depsgraph.evaluated_id_get(*b_mat_orig));
|
|
|
|
|
BL::Material *b_mat = &b_mat_;
|
2011-04-27 11:58:34 +00:00
|
|
|
Shader *shader;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* test if we need to sync */
|
2012-11-21 13:00:51 +00:00
|
|
|
if(shader_map.sync(&shader, *b_mat) || update_all) {
|
2011-04-27 11:58:34 +00:00
|
|
|
ShaderGraph *graph = new ShaderGraph();
|
|
|
|
|
|
2011-10-03 17:42:24 +00:00
|
|
|
shader->name = b_mat->name().c_str();
|
Cycles: Render Passes
Currently supported passes:
* Combined, Z, Normal, Object Index, Material Index, Emission, Environment,
Diffuse/Glossy/Transmission x Direct/Indirect/Color
Not supported yet:
* UV, Vector, Mist
Only enabled for CPU devices at the moment, will do GPU tweaks tommorrow,
also for environment importance sampling.
Documentation:
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Passes
2012-01-25 17:23:52 +00:00
|
|
|
shader->pass_id = b_mat->pass_index();
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2011-05-31 11:28:04 +00:00
|
|
|
/* create nodes */
|
|
|
|
|
if(b_mat->use_nodes() && b_mat->node_tree()) {
|
2011-04-27 11:58:34 +00:00
|
|
|
BL::ShaderNodeTree b_ntree(b_mat->node_tree());
|
|
|
|
|
|
2017-07-21 11:53:13 +02:00
|
|
|
add_nodes(scene, b_engine, b_data, b_scene, b_scene_layer, !preview, graph, b_ntree);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
2011-05-31 11:28:04 +00:00
|
|
|
else {
|
2016-05-07 19:48:28 +02:00
|
|
|
DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
|
|
|
|
|
diffuse->color = get_float3(b_mat->diffuse_color());
|
|
|
|
|
graph->add(diffuse);
|
2011-05-31 11:28:04 +00:00
|
|
|
|
2016-05-07 19:48:28 +02:00
|
|
|
ShaderNode *out = graph->output();
|
|
|
|
|
graph->connect(diffuse->output("BSDF"), out->input("Surface"));
|
2011-05-31 11:28:04 +00:00
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2011-09-27 20:37:24 +00:00
|
|
|
/* settings */
|
|
|
|
|
PointerRNA cmat = RNA_pointer_get(&b_mat->ptr, "cycles");
|
2013-06-18 09:36:00 +00:00
|
|
|
shader->use_mis = get_boolean(cmat, "sample_as_light");
|
|
|
|
|
shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow");
|
2013-12-29 22:19:38 +01:00
|
|
|
shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume");
|
2016-02-10 15:09:45 +01:00
|
|
|
shader->volume_sampling_method = get_volume_sampling(cmat);
|
|
|
|
|
shader->volume_interpolation_method = get_volume_interpolation(cmat);
|
2016-08-02 05:13:58 -04:00
|
|
|
shader->displacement_method = (experimental) ? get_displacement_method(cmat) : DISPLACE_BUMP;
|
2011-09-27 20:37:24 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
shader->set_graph(graph);
|
2016-12-14 23:47:39 +01:00
|
|
|
|
2017-03-31 15:29:20 +02:00
|
|
|
/* By simplifying the shader graph as soon as possible, some
|
|
|
|
|
* redundant shader nodes might be removed which prevents loading
|
|
|
|
|
* unnecessary attributes later.
|
2016-12-14 23:47:39 +01:00
|
|
|
*
|
2017-03-31 15:29:20 +02:00
|
|
|
* However, since graph simplification also accounts for e.g. mix
|
|
|
|
|
* weight, this would cause frequent expensive resyncs in interactive
|
|
|
|
|
* sessions, so for those sessions optimization is only performed
|
|
|
|
|
* right before compiling.
|
|
|
|
|
*/
|
2016-12-14 23:47:39 +01:00
|
|
|
if(!preview) {
|
2017-04-04 13:36:58 +02:00
|
|
|
pool.push(function_bind(&ShaderGraph::simplify, graph, scene));
|
|
|
|
|
/* NOTE: Update shaders out of the threads since those routines
|
|
|
|
|
* are accessing and writing to a global context.
|
|
|
|
|
*/
|
|
|
|
|
updated_shaders.insert(shader);
|
2017-03-31 15:29:20 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* NOTE: Update tagging can access links which are being
|
|
|
|
|
* optimized out.
|
|
|
|
|
*/
|
|
|
|
|
shader->tag_update(scene);
|
2016-12-14 23:47:39 +01:00
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
2016-12-14 23:47:39 +01:00
|
|
|
|
|
|
|
|
pool.wait_work();
|
2017-04-04 13:36:58 +02:00
|
|
|
|
|
|
|
|
foreach(Shader *shader, updated_shaders) {
|
|
|
|
|
shader->tag_update(scene);
|
|
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Sync World */
|
|
|
|
|
|
2012-11-21 13:00:51 +00:00
|
|
|
void BlenderSync::sync_world(bool update_all)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
Background *background = scene->background;
|
|
|
|
|
Background prevbackground = *background;
|
|
|
|
|
|
|
|
|
|
BL::World b_world = b_scene.world();
|
|
|
|
|
|
2012-11-21 13:00:51 +00:00
|
|
|
if(world_recalc || update_all || b_world.ptr.data != world_map) {
|
2016-05-14 14:50:03 +02:00
|
|
|
Shader *shader = scene->default_background;
|
2011-04-27 11:58:34 +00:00
|
|
|
ShaderGraph *graph = new ShaderGraph();
|
|
|
|
|
|
|
|
|
|
/* create nodes */
|
2011-05-31 11:28:04 +00:00
|
|
|
if(b_world && b_world.use_nodes() && b_world.node_tree()) {
|
2011-04-27 11:58:34 +00:00
|
|
|
BL::ShaderNodeTree b_ntree(b_world.node_tree());
|
|
|
|
|
|
2017-07-21 11:53:13 +02:00
|
|
|
add_nodes(scene, b_engine, b_data, b_scene, b_scene_layer, !preview, graph, b_ntree);
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2014-01-08 11:00:06 +01:00
|
|
|
/* volume */
|
|
|
|
|
PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
|
|
|
|
|
shader->heterogeneous_volume = !get_boolean(cworld, "homogeneous_volume");
|
2016-02-10 15:09:45 +01:00
|
|
|
shader->volume_sampling_method = get_volume_sampling(cworld);
|
|
|
|
|
shader->volume_interpolation_method = get_volume_interpolation(cworld);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
2011-05-31 11:28:04 +00:00
|
|
|
else if(b_world) {
|
2016-05-07 19:48:28 +02:00
|
|
|
BackgroundNode *background = new BackgroundNode();
|
|
|
|
|
background->color = get_float3(b_world.horizon_color());
|
|
|
|
|
graph->add(background);
|
2011-05-31 11:28:04 +00:00
|
|
|
|
2016-05-07 19:48:28 +02:00
|
|
|
ShaderNode *out = graph->output();
|
|
|
|
|
graph->connect(background->output("Background"), out->input("Surface"));
|
2011-05-31 11:28:04 +00:00
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2012-02-28 16:45:08 +00:00
|
|
|
if(b_world) {
|
2013-06-10 20:34:34 +00:00
|
|
|
/* AO */
|
2012-02-28 16:45:08 +00:00
|
|
|
BL::WorldLighting b_light = b_world.light_settings();
|
|
|
|
|
|
2012-02-28 19:43:33 +00:00
|
|
|
if(b_light.use_ambient_occlusion())
|
2012-02-28 16:45:08 +00:00
|
|
|
background->ao_factor = b_light.ao_factor();
|
2012-02-28 19:43:33 +00:00
|
|
|
else
|
2012-02-28 16:45:08 +00:00
|
|
|
background->ao_factor = 0.0f;
|
2012-02-28 19:43:33 +00:00
|
|
|
|
|
|
|
|
background->ao_distance = b_light.distance();
|
2013-06-10 20:34:34 +00:00
|
|
|
|
|
|
|
|
/* visibility */
|
|
|
|
|
PointerRNA cvisibility = RNA_pointer_get(&b_world.ptr, "cycles_visibility");
|
|
|
|
|
uint visibility = 0;
|
|
|
|
|
|
|
|
|
|
visibility |= get_boolean(cvisibility, "camera")? PATH_RAY_CAMERA: 0;
|
|
|
|
|
visibility |= get_boolean(cvisibility, "diffuse")? PATH_RAY_DIFFUSE: 0;
|
|
|
|
|
visibility |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0;
|
|
|
|
|
visibility |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0;
|
2014-09-05 16:17:24 +02:00
|
|
|
visibility |= get_boolean(cvisibility, "scatter")? PATH_RAY_VOLUME_SCATTER: 0;
|
2013-06-10 20:34:34 +00:00
|
|
|
|
|
|
|
|
background->visibility = visibility;
|
2012-02-28 16:45:08 +00:00
|
|
|
}
|
2015-11-23 17:24:49 +05:00
|
|
|
else {
|
|
|
|
|
background->ao_factor = 0.0f;
|
|
|
|
|
background->ao_distance = FLT_MAX;
|
|
|
|
|
}
|
2012-02-28 16:45:08 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
shader->set_graph(graph);
|
|
|
|
|
shader->tag_update(scene);
|
2014-01-08 23:12:54 +01:00
|
|
|
background->tag_update(scene);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
2011-08-28 13:55:59 +00:00
|
|
|
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
2013-04-11 12:49:57 +00:00
|
|
|
|
|
|
|
|
/* when doing preview render check for BI's transparency settings,
|
2015-09-14 02:21:15 +10:00
|
|
|
* this is so because Blender's preview render routines are not able
|
2013-04-11 12:49:57 +00:00
|
|
|
* to tweak all cycles's settings depending on different circumstances
|
|
|
|
|
*/
|
|
|
|
|
if(b_engine.is_preview() == false)
|
|
|
|
|
background->transparent = get_boolean(cscene, "film_transparent");
|
|
|
|
|
else
|
|
|
|
|
background->transparent = b_scene.render().alpha_mode() == BL::RenderSettings::alpha_mode_TRANSPARENT;
|
|
|
|
|
|
2015-11-24 13:21:40 +05:00
|
|
|
background->use_shader = render_layer.use_background_shader;
|
|
|
|
|
background->use_ao = render_layer.use_background_ao;
|
2011-08-28 13:55:59 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
if(background->modified(prevbackground))
|
|
|
|
|
background->tag_update(scene);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Sync Lamps */
|
|
|
|
|
|
2012-11-21 13:00:51 +00:00
|
|
|
void BlenderSync::sync_lamps(bool update_all)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2016-05-14 14:50:03 +02:00
|
|
|
shader_map.set_default(scene->default_light);
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
|
/* lamp loop */
|
Depsgraph: Initial groundwork for copy-on-write support
< Dependency graph Copy-on-Write >
--------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
This is an initial commit of Copy-on-write support added to dependency graph.
Main priority for now: get playback (Alt-A) and all operators (selection,
transform etc) to work with the new concept of clear separation between
evaluated data coming from dependency graph and original data coming from
.blend file (and stored in bmain).
= How does this work? =
The idea is to support Copy-on-Write on the ID level. This means, we duplicate
the whole ID before we cann it's evaluaiton function. This is currently done
in the following way:
- At the depsgraph construction time we create "shallow" copy of the ID
datablock, just so we know it's pointer in memory and can use for function
bindings.
- At the evaluaiton time, the copy of ID get's "expanded" (needs a better
name internally, so it does not conflict with expanding datablocks during
library linking), which means the content of the datablock is being
copied over and all IDs are getting remapped to the copied ones.
Currently we do the whole copy, in the future we will support some tricks
here to prevent duplicating geometry arrays (verts, edges, loops, faces
and polys) when we don't need that.
- Evaluation functions are operating on copied datablocks and never touching
original datablock.
- There are some cases when we need to know non-ID pointers for function
bindings. This mainly applies to scene collections and armatures. The
idea of dealing with this is to "expand" copy-on-write datablock at
the dependency graph build time. This might introduce some slowdown to the
dependency graph construction time, but allows us to have minimal changes
in the code and avoid any hash look-up from evaluation function (one of
the ideas to avoid using pointers as function bindings is to pass name
of layer or a bone to the evaluation function and look up actual data based
on that name).
Currently there is a special function in depsgraph which does such a
synchronization, in the future we might want to make it more generic.
At some point we need to synchronize copy-on-write version of datablock with
the original version. This happens, i.e., when we change active object or
change selection. We don't want any actual evaluation of update flush happening
for such thins, so now we have a special update tag:
DEG_id_tag_update((id, DEG_TAG_COPY_ON_WRITE)
- For the render engines we now have special call for the dependency graph to
give evaluated datablock for the given original one. This isn't fully ideal
but allows to have Cycles viewport render.
This is definitely a subject for further investigation / improvement.
This call will tag copy-on-write component tagged for update without causing
updates to be flushed to any other objects, causing chain reaction of updates.
This tag is handy when selection in the scene changes.
This basically summarizes ideas underneath this commit. The code should be
reasonably documented.
Here is a demo of dependency graph with all copy-on-write stuff in it:
https://developer.blender.org/F635468
= What to expect to (not) work? =
- Only meshes are properly-ish aware of copy-on-write currently, Non-mesh
geometry will probably crash or will not work at all.
- Armatures will need similar depsgraph built-time expansion of the copied
datablock.
- There are some extra tags / relations added, to keep things demo-able but
which are slowing things down for evaluation.
- Edit mode works for until click selection is used (due to the selection
code using EditDerivedMesh created ad-hoc).
- Lots of tools will lack tagging synchronization of copied datablock for
sync with original ID.
= How to move forward? =
There is some tedious work related on going over all the tools, checking
whether they need to work with original or final evaluated object and make
the required changes.
Additionally, there need synchronization tag done in fair amount of tools
and operators as well. For example, currently it's not possible to change
render engine without re-opening the file or forcing dependency graph for
re-build via python console.
There is also now some thoughts required about copying evaluated properties
between objects or from collection to a new object. Perhaps easiest way
would be to move base flag flush to Object ID node and tag new objects for
update instead of doing manual copy.
here is some WIP patch which moves such evaluaiton / flush:
https://developer.blender.org/F635479
Lots of TODOs in the code, with possible optimization.
= How to test? =
This is a feature under heavy development, so obviously it is disabled by
default. The only reason it goes to 2.8 branch is to avoid possible merge
hell.
In order to enable this feature use WITH_DEPSGRAPH_COPY_ON_WRITE CMake
configuration option.
2017-06-14 10:26:24 +02:00
|
|
|
BL::BlendData::lamps_iterator b_lamp_orig;
|
|
|
|
|
for(b_data.lamps.begin(b_lamp_orig);
|
|
|
|
|
b_lamp_orig != b_data.lamps.end();
|
|
|
|
|
++b_lamp_orig)
|
|
|
|
|
{
|
|
|
|
|
/* TODO(sergey): Iterate over evaluated data rather than using mapping. */
|
|
|
|
|
BL::Lamp b_lamp_(b_depsgraph.evaluated_id_get(*b_lamp_orig));
|
|
|
|
|
BL::Lamp *b_lamp = &b_lamp_;
|
2011-04-27 11:58:34 +00:00
|
|
|
Shader *shader;
|
2014-09-19 12:57:09 +02:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* test if we need to sync */
|
2012-11-21 13:00:51 +00:00
|
|
|
if(shader_map.sync(&shader, *b_lamp) || update_all) {
|
2011-04-27 11:58:34 +00:00
|
|
|
ShaderGraph *graph = new ShaderGraph();
|
|
|
|
|
|
|
|
|
|
/* create nodes */
|
2011-05-31 11:28:04 +00:00
|
|
|
if(b_lamp->use_nodes() && b_lamp->node_tree()) {
|
2011-10-03 17:42:24 +00:00
|
|
|
shader->name = b_lamp->name().c_str();
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
|
BL::ShaderNodeTree b_ntree(b_lamp->node_tree());
|
|
|
|
|
|
2017-07-21 11:53:13 +02:00
|
|
|
add_nodes(scene, b_engine, b_data, b_scene, b_scene_layer, !preview, graph, b_ntree);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
2011-05-31 11:28:04 +00:00
|
|
|
else {
|
2011-11-08 22:38:10 +00:00
|
|
|
float strength = 1.0f;
|
|
|
|
|
|
|
|
|
|
if(b_lamp->type() == BL::Lamp::type_POINT ||
|
|
|
|
|
b_lamp->type() == BL::Lamp::type_SPOT ||
|
|
|
|
|
b_lamp->type() == BL::Lamp::type_AREA)
|
2012-06-09 18:56:12 +00:00
|
|
|
{
|
2011-11-08 22:38:10 +00:00
|
|
|
strength = 100.0f;
|
2012-06-09 18:56:12 +00:00
|
|
|
}
|
2011-05-31 11:28:04 +00:00
|
|
|
|
2016-05-07 19:48:28 +02:00
|
|
|
EmissionNode *emission = new EmissionNode();
|
|
|
|
|
emission->color = get_float3(b_lamp->color());
|
|
|
|
|
emission->strength = strength;
|
|
|
|
|
graph->add(emission);
|
2011-05-31 11:28:04 +00:00
|
|
|
|
2016-05-07 19:48:28 +02:00
|
|
|
ShaderNode *out = graph->output();
|
|
|
|
|
graph->connect(emission->output("Emission"), out->input("Surface"));
|
2011-05-31 11:28:04 +00:00
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
|
shader->set_graph(graph);
|
|
|
|
|
shader->tag_update(scene);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BlenderSync::sync_shaders()
|
|
|
|
|
{
|
2012-11-21 13:00:51 +00:00
|
|
|
/* for auto refresh images */
|
|
|
|
|
bool auto_refresh_update = false;
|
|
|
|
|
|
|
|
|
|
if(preview) {
|
|
|
|
|
ImageManager *image_manager = scene->image_manager;
|
|
|
|
|
int frame = b_scene.frame_current();
|
|
|
|
|
auto_refresh_update = image_manager->set_animation_frame_update(frame);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
shader_map.pre_sync();
|
|
|
|
|
|
2012-11-21 13:00:51 +00:00
|
|
|
sync_world(auto_refresh_update);
|
|
|
|
|
sync_lamps(auto_refresh_update);
|
|
|
|
|
sync_materials(auto_refresh_update);
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
|
/* false = don't delete unused shaders, not supported */
|
|
|
|
|
shader_map.post_sync(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CCL_NAMESPACE_END
|
|
|
|
|
|