
commit90778901c9
Merge:76eebd9
3bf0026
Author: Schoen <schoepas@deher1m1598.emea.adsint.biz> Date: Mon Apr 3 07:52:05 2017 +0200 Merge branch 'master' into cycles_disney_brdf commit76eebd9379
Author: Schoen <schoepas@deher1m1598.emea.adsint.biz> Date: Thu Mar 30 15:34:20 2017 +0200 Updated copyright for the new files. commit013f4a152a
Author: Schoen <schoepas@deher1m1598.emea.adsint.biz> Date: Thu Mar 30 15:32:55 2017 +0200 Switched from multiplication of base and subsurface color to blending between them using the subsurface parameter. commit482ec5d1f2
Author: Schoen <schoepas@deher1m1598.emea.adsint.biz> Date: Mon Mar 13 15:47:12 2017 +0100 Fixed a bug that caused an additional white diffuse closure call when using path tracing. commit26e906d162
Merge:0593b8c
223aff9
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Feb 6 11:32:31 2017 +0100 Merge branch 'master' into cycles_disney_brdf commit0593b8c51b
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Feb 6 11:30:36 2017 +0100 Fixed the broken GLSL shader and implemented the Disney BRDF in the real-time view port. commit8c7e11423b
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Feb 3 14:24:05 2017 +0100 Fix to comply strict compiler flags and some code cleanup commit17724e9d2d
Merge:379ba34
520afa2
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jan 24 09:59:58 2017 +0100 Merge branch 'master' into cycles_disney_brdf commit379ba346b0
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jan 24 09:28:56 2017 +0100 Renamed the Disney BSDF to Principled BSDF. commitf80dcb4f34
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Dec 2 13:55:12 2016 +0100 Removed reflection call when roughness is low because of artifacts. commit732db8a57f
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed Nov 16 09:22:25 2016 +0100 Indication if to use fresnel is now handled via the type of the BSDF. commit0103659f5e
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Nov 11 13:04:11 2016 +0100 Fixed an error in the clearcoat where it appeared too bright for default light sources (like directional lights) commit0aa68f5335
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Nov 7 12:04:38 2016 +0100 Resolved inconsistencies in using tabs and spaces commitf5897a9494
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Nov 7 08:13:41 2016 +0100 Improved the clearcoat part by using GTR1 instead of GTR2 commit3dfc240e61
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Oct 31 11:31:36 2016 +0100 Use reflection BSDF for glossy reflections when roughness is 0.0 to reduce computational expense and some code cleanup Code cleanup includes: - Code style cleanup and removed unused code - Consolidated code in the bsdf_microfacet_multi_impl.h to reduce some computational expense commita2dd0c5faf
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed Oct 26 08:51:10 2016 +0200 Fixed glossy reflections and refractions for low roughness values and cleaned up the code. For low roughness values, the reflections had some strange behavior. commit9817375912
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Oct 25 12:37:40 2016 +0200 Removed default values in setup functions and added extra functions for GGX with fresnel. commitbbc5d9d452
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Oct 25 11:09:36 2016 +0200 Switched from uniform to cosine hemisphere sampling for the diffuse and the sheen part. commitd52d8f2813
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Oct 24 16:17:13 2016 +0200 Removed the color parameters from the diffuse and sheen shader and use them as closure weights instead. commit8f3d927385
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Oct 24 09:57:06 2016 +0200 Fixed the issue with artifacts when using anisotropy without linking the tangent input to a tangent node. commitd93f680db9
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Oct 24 09:14:51 2016 +0200 Added subsurface radius parameter to control the per color channel effection radius of the subsurface scattering. commitc708c3e53b
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Oct 24 08:14:10 2016 +0200 Rearranged the inputs of the shader. commitdfbfff9c38
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Oct 21 09:27:05 2016 +0200 Put spaces in the parameter names of the shader node commite5a748ced1
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Oct 21 08:51:20 2016 +0200 Removed code that isn't in use anymore commit75992bebc1
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Oct 21 08:50:07 2016 +0200 Code style cleanup commit4dfcf455f7
Merge:243a0e3
2cd6a89
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Thu Oct 20 10:41:50 2016 +0200 Merge branch 'master' into cycles_disney_brdf commit243a0e3eb8
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Thu Oct 20 10:01:45 2016 +0200 Switching between OSL and SVM is more consistant now when using Disney BSDF. There were some minor differences in the OSL implementation, e.g. the refraction roughness was missing. commit2a5ac50922
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Sep 27 09:17:57 2016 +0200 Fixed a bug that caused transparency to be always white when using OSL and selecting GGX as distribution of the Disney BSDF commite1fa862391
Merge:d0530a8
7f76f6f
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Sep 27 08:59:32 2016 +0200 Merge branch 'master' into cycles_disney_brdf commitd0530a8af0
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Sep 27 08:53:18 2016 +0200 Cleanup the Disney BSDF implementation and removing unneeded files. commit3f4fc826bd
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Sep 27 08:36:07 2016 +0200 Unified the OSL implementation of the Disney clearcoat as a simple microfacet shader like it was previously done in SVM commit4d3a0032ec
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Sep 26 12:35:36 2016 +0200 Enhanced performance for Disney materials without subsurface scattering commit3cd5eb56cf
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Sep 16 08:47:56 2016 +0200 Fixed a bug in the Disney BSDF that caused specular reflections to be too bright and diffuse is now reacting to the roughness again - A normalization for the fresnel was missing which caused the specular reflections to become too bright for the single-scatter GGX - The roughness value for the diffuse BSSRDF part has always been overwritten and thus always 0 - Also the performance for refractive materials with roughness=0.0 has been improved commit7cb37d7119
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Thu Sep 8 12:24:43 2016 +0200 Added selection field to the Disney BSDF node for switching between "Multiscatter GGX" and "GGX" In the "GGX" mode there is an additional parameter for changing the refraction roughness for materials with smooth surfaces and rough interns (e.g. honey). With the "Multiscatter GGX" this effect can't be produced at the moment and so here will be no separation of the two roughness values. commitcdd29d06bb
Merge:02c315a
b40d1c1
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Sep 6 15:59:05 2016 +0200 Merge branch 'master' into cycles_disney_brdf commit02c315aeb0
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Sep 6 15:16:09 2016 +0200 Implemented the OSL part of the Disney shader commit5f880293ae
Merge:630b80e
b399a6d
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Sep 2 10:53:36 2016 +0200 Merge branch 'master' into cycles_disney_brdf commit630b80e08b
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Sep 2 10:52:13 2016 +0200 Fresnel in the microfacet multiscatter implementation improved commit0d9f4d7acb
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Aug 26 11:11:05 2016 +0200 Fixed refraction roughness problem (refractions were always 100% rough) and set IOR of clearcoat to 1.5 commit9eed34c7d9
Merge:ef29aae
ae475e3
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Aug 16 15:22:32 2016 +0200 Merge branch 'master' into cycles_disney_brdf commitef29aaee1a
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Aug 16 15:17:12 2016 +0200 Implemented the fresnel in the multi-scatter GGX for the Disney BSDF - The specular/metallic part uses the multi-scatter GGX - The fresnel of the metallic part is controlled by the specular value - The color of the reflection part when using transparency can be controlled by the specularTint value commit88567af085
Merge:cc267e5
285e082
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed Aug 3 15:05:09 2016 +0200 Merge branch 'master' into cycles_disney_brdf commitcc267e52f2
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed Aug 3 15:00:25 2016 +0200 Implemented the Disney clearcoat as a variation of the microfacet bsdf, removed the transparency roughness again and added an input for anisotropic rotations commit81f6c06b1f
Merge:ece5a08
7065022
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed Aug 3 11:42:02 2016 +0200 Merge branch 'master' into cycles_disney_brdf commitece5a08e0d
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jul 26 16:29:21 2016 +0200 Base color now applied again to the refraction of transparent Disney materials commite3aff6849e
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jul 26 16:05:19 2016 +0200 Added subsurface color parameter to the Disney shader commitb3ca6d8a2f
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jul 26 12:30:25 2016 +0200 Improvement of the SSS in the Disney shader * Now the bump normal is correctly used for the SSS. * SSS in Disney uses the Disney diffuse shader commitd68729300e
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jul 26 12:23:13 2016 +0200 Better calculation of the Disney diffuse part Now the values for NdotL und NdotV are clamped to 0.0f for a better look when using normal maps commitcb6e500b12
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Jul 25 16:26:42 2016 +0200 Now one can disable specular reflactions again by setting specular and metallic to 0 (cracked this in the previous commit) commitbfb9cb11b5
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Jul 25 16:11:07 2016 +0200 fixed the Disney SSS and cleaned the initialization of the Disney shaders commit642c0fdad1
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Jul 25 16:09:55 2016 +0200 fixed an error that was caused by the missing LABEL_REFLECT in the Disney diffuse shader commitc10b484dca
Author: Jens Verwiebe <info@jensverwiebe.de> Date: Fri Jul 22 01:15:21 2016 +0200 Rollback attempt to fix sss crashing, it prevented crash by disabling sss completely, thus useless commit462bba3f97
Author: Jens Verwiebe <info@jensverwiebe.de> Date: Thu Jul 21 23:11:59 2016 +0200 Add an undef for sc_next for safety commit32d348577d
Author: Jens Verwiebe <info@jensverwiebe.de> Date: Thu Jul 21 00:15:48 2016 +0200 Attempt to fix Disney SSS commitdbad91ca6d
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed Jul 20 11:13:00 2016 +0200 Added a roughness parameter for refractions (for scattering of the rays within an object) With this, one can create a translucent material with a smooth surface and with a milky look. The final refraction roughness has to be calculated using the surface roughness and the refraction roughness because those two are correlated for refractions. If a ray hits a rough surface of a translucent material, it is scattered while entering the surface. Then it is scattered further within the object. The calculation I'm using is the following: RefrRoughnessFinal = 1.0 - (1.0 - Roughness) * (1.0 - RefrRoughness) commit50ea5e3e34
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue Jun 7 10:24:50 2016 +0200 Disney BSDF is now supporting CUDA commit10974cc826
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 31 11:18:07 2016 +0200 Added parameters IOR and Transparency for refractions With this, the Disney BRDF/BSSRDF is extended by the BTDF part. commit218202c090
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon May 30 15:08:18 2016 +0200 Added an additional normal for the clearcoat With this normal one can simulate a thin layer of clearcoat by applying a smoother normal map than the original to this input commitdd139ead7e
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon May 30 12:40:56 2016 +0200 Switched to the improved subsurface scattering from Christensen and Burley commit11160fa4e1
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon May 30 10:16:30 2016 +0200 Added Disney Sheen shader as a preparation to get to a BSSRDF commitcee4fe0cc9
Merge:4f955d0
6b5bab6
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon May 30 09:08:09 2016 +0200 Merge branch 'cycles_disney_brdf' of git.blender.org:blender into cycles_disney_brdf Conflicts: intern/cycles/kernel/closure/bsdf_disney_clearcoat.h intern/cycles/kernel/closure/bsdf_disney_diffuse.h intern/cycles/kernel/closure/bsdf_disney_specular.h intern/cycles/kernel/closure/bsdf_util.h intern/cycles/kernel/osl/CMakeLists.txt intern/cycles/kernel/osl/bsdf_disney_clearcoat.cpp intern/cycles/kernel/osl/bsdf_disney_diffuse.cpp intern/cycles/kernel/osl/bsdf_disney_specular.cpp intern/cycles/kernel/osl/osl_closures.h intern/cycles/kernel/shaders/node_disney_bsdf.osl intern/cycles/render/nodes.cpp intern/cycles/render/nodes.h commit4f955d0523
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 24 16:38:23 2016 +0200 SVM and OSL are both working for the simple version of the Disney BRDF commit1f5c41874b
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 24 09:58:50 2016 +0200 Disney node can be used without SVM and started to cleanup the OSL implementation There is still some wrong behavior for SVM for the Schlick Fresnel part at the specular and clearcoat commitd4b814e930
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 18 10:22:29 2016 +0200 Switched from a parameter struct for Disney parameters to ShaderClosure params commitb86a1f5ba5
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 18 10:19:57 2016 +0200 Added additional variables for storing parameters in the ShaderClosure struct commit585b886236
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 17 12:03:17 2016 +0200 added output parameter to the DisneyBsdfNode That has been forgotten after removing the inheritance of BsdfNode commitf91a286398
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 17 10:40:48 2016 +0200 removed BsdfNode class inheritance for DisneyBsdfNode That's due to a naming difference. The Disney BSDF uses the name 'Base Color' while the BsdfNode had a 'Color' input. That caused a text message to be printed while rendering. commit30da91c9c5
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 4 16:08:10 2016 +0200 disney implementation cleaned commit30d41da0f0
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 4 13:23:07 2016 +0200 added the disney brdf as a shader node commit1f099fce24
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 3 16:54:49 2016 +0200 added clearcoat implementation commit00a1378b98
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Apr 29 22:56:49 2016 +0200 disney diffuse und specular implemented commit6baa7a7eb7
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Apr 18 15:21:32 2016 +0200 disney diffuse is working correctly commitd8fa169bf3
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Apr 18 08:41:53 2016 +0200 added vessel for disney diffuse shader commit6b5bab6cec
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 18 10:22:29 2016 +0200 Switched from a parameter struct for Disney parameters to ShaderClosure params commitf6499c2676
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 18 10:19:57 2016 +0200 Added additional variables for storing parameters in the ShaderClosure struct commit7100640b65
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 17 12:03:17 2016 +0200 added output parameter to the DisneyBsdfNode That has been forgotten after removing the inheritance of BsdfNode commit419ee54411
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 17 10:40:48 2016 +0200 removed BsdfNode class inheritance for DisneyBsdfNode That's due to a naming difference. The Disney BSDF uses the name 'Base Color' while the BsdfNode had a 'Color' input. That caused a text message to be printed while rendering. commit6006f91e87
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 4 16:08:10 2016 +0200 disney implementation cleaned commit0ed0895914
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Wed May 4 13:23:07 2016 +0200 added the disney brdf as a shader node commit0630b742d7
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Tue May 3 16:54:49 2016 +0200 added clearcoat implementation commit9f3d39744b
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Fri Apr 29 22:56:49 2016 +0200 disney diffuse und specular implemented commit9b26206376
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Apr 18 15:21:32 2016 +0200 disney diffuse is working correctly commit4711a3927d
Author: Pascal Schoen <pascal_schoen@gmx.net> Date: Mon Apr 18 08:41:53 2016 +0200 added vessel for disney diffuse shader Differential Revision: https://developer.blender.org/D2313
1411 lines
46 KiB
C++
1411 lines
46 KiB
C++
/*
|
|
* Copyright 2011-2013 Blender Foundation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "render/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"
|
|
|
|
#include "blender/blender_texture.h"
|
|
#include "blender/blender_sync.h"
|
|
#include "blender/blender_util.h"
|
|
|
|
#include "util/util_debug.h"
|
|
#include "util/util_foreach.h"
|
|
#include "util/util_string.h"
|
|
#include "util/util_set.h"
|
|
#include "util/util_task.h"
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
typedef map<void*, ShaderInput*> PtrInputMap;
|
|
typedef map<void*, ShaderOutput*> PtrOutputMap;
|
|
typedef map<string, ConvertNode*> ProxyMap;
|
|
|
|
/* Find */
|
|
|
|
void BlenderSync::find_shader(BL::ID& id,
|
|
vector<Shader*>& used_shaders,
|
|
Shader *default_shader)
|
|
{
|
|
Shader *shader = (id)? shader_map.find(id): default_shader;
|
|
|
|
used_shaders.push_back(shader);
|
|
shader->tag_used(scene);
|
|
}
|
|
|
|
/* 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);
|
|
}
|
|
|
|
static DisplacementMethod get_displacement_method(PointerRNA& ptr)
|
|
{
|
|
return (DisplacementMethod)get_enum(ptr,
|
|
"displacement_method",
|
|
DISPLACE_NUM_METHODS,
|
|
DISPLACE_BUMP);
|
|
}
|
|
|
|
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>
|
|
static InterpolationType get_image_interpolation(NodeType& b_node)
|
|
{
|
|
int value = b_node.interpolation();
|
|
return (InterpolationType)validate_enum_value(value,
|
|
INTERPOLATION_NUM_TYPES,
|
|
INTERPOLATION_LINEAR);
|
|
}
|
|
|
|
template<typename NodeType>
|
|
static ExtensionType get_image_extension(NodeType& b_node)
|
|
{
|
|
int value = b_node.extension();
|
|
return (ExtensionType)validate_enum_value(value,
|
|
EXTENSION_NUM_TYPES,
|
|
EXTENSION_REPEAT);
|
|
}
|
|
|
|
/* Graph */
|
|
|
|
static BL::NodeSocket get_node_output(BL::Node& b_node, const string& name)
|
|
{
|
|
BL::Node::outputs_iterator b_out;
|
|
|
|
for(b_node.outputs.begin(b_out); b_out != b_node.outputs.end(); ++b_out)
|
|
if(b_out->name() == name)
|
|
return *b_out;
|
|
|
|
assert(0);
|
|
|
|
return *b_out;
|
|
}
|
|
|
|
static float3 get_node_output_rgba(BL::Node& b_node, const string& name)
|
|
{
|
|
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]);
|
|
}
|
|
|
|
static float get_node_output_value(BL::Node& b_node, const string& name)
|
|
{
|
|
BL::NodeSocket b_sock = get_node_output(b_node, name);
|
|
return RNA_float_get(&b_sock.ptr, "default_value");
|
|
}
|
|
|
|
static float3 get_node_output_vector(BL::Node& b_node, const string& name)
|
|
{
|
|
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]);
|
|
}
|
|
|
|
static SocketType::Type convert_socket_type(BL::NodeSocket& b_socket)
|
|
{
|
|
switch(b_socket.type()) {
|
|
case BL::NodeSocket::type_VALUE:
|
|
return SocketType::FLOAT;
|
|
case BL::NodeSocket::type_INT:
|
|
return SocketType::INT;
|
|
case BL::NodeSocket::type_VECTOR:
|
|
return SocketType::VECTOR;
|
|
case BL::NodeSocket::type_RGBA:
|
|
return SocketType::COLOR;
|
|
case BL::NodeSocket::type_STRING:
|
|
return SocketType::STRING;
|
|
case BL::NodeSocket::type_SHADER:
|
|
return SocketType::CLOSURE;
|
|
|
|
default:
|
|
return SocketType::UNDEFINED;
|
|
}
|
|
}
|
|
|
|
static void set_default_value(ShaderInput *input,
|
|
BL::NodeSocket& b_sock,
|
|
BL::BlendData& b_data,
|
|
BL::ID& b_id)
|
|
{
|
|
Node *node = input->parent;
|
|
const SocketType& socket = input->socket_type;
|
|
|
|
/* copy values for non linked inputs */
|
|
switch(input->type()) {
|
|
case SocketType::FLOAT: {
|
|
node->set(socket, get_float(b_sock.ptr, "default_value"));
|
|
break;
|
|
}
|
|
case SocketType::INT: {
|
|
node->set(socket, get_int(b_sock.ptr, "default_value"));
|
|
break;
|
|
}
|
|
case SocketType::COLOR: {
|
|
node->set(socket, float4_to_float3(get_float4(b_sock.ptr, "default_value")));
|
|
break;
|
|
}
|
|
case SocketType::NORMAL:
|
|
case SocketType::POINT:
|
|
case SocketType::VECTOR: {
|
|
node->set(socket, get_float3(b_sock.ptr, "default_value"));
|
|
break;
|
|
}
|
|
case SocketType::STRING: {
|
|
node->set(socket, (ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value")));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void get_tex_mapping(TextureMapping *mapping, BL::TexMapping& b_mapping)
|
|
{
|
|
if(!b_mapping)
|
|
return;
|
|
|
|
mapping->translation = get_float3(b_mapping.translation());
|
|
mapping->rotation = get_float3(b_mapping.rotation());
|
|
mapping->scale = get_float3(b_mapping.scale());
|
|
mapping->type = (TextureMapping::Type)b_mapping.vector_type();
|
|
|
|
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();
|
|
}
|
|
|
|
static void get_tex_mapping(TextureMapping *mapping,
|
|
BL::ShaderNodeMapping& b_mapping)
|
|
{
|
|
if(!b_mapping)
|
|
return;
|
|
|
|
mapping->translation = get_float3(b_mapping.translation());
|
|
mapping->rotation = get_float3(b_mapping.rotation());
|
|
mapping->scale = get_float3(b_mapping.scale());
|
|
mapping->type = (TextureMapping::Type)b_mapping.vector_type();
|
|
|
|
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());
|
|
}
|
|
|
|
static bool is_output_node(BL::Node& b_node)
|
|
{
|
|
return (b_node.is_a(&RNA_ShaderNodeOutputMaterial)
|
|
|| b_node.is_a(&RNA_ShaderNodeOutputWorld)
|
|
|| b_node.is_a(&RNA_ShaderNodeOutputLamp));
|
|
}
|
|
|
|
static ShaderNode *add_node(Scene *scene,
|
|
BL::RenderEngine& b_engine,
|
|
BL::BlendData& b_data,
|
|
BL::Scene& b_scene,
|
|
const bool background,
|
|
ShaderGraph *graph,
|
|
BL::ShaderNodeTree& b_ntree,
|
|
BL::ShaderNode& b_node)
|
|
{
|
|
ShaderNode *node = NULL;
|
|
|
|
/* existing blender nodes */
|
|
if(b_node.is_a(&RNA_ShaderNodeRGBCurve)) {
|
|
BL::ShaderNodeRGBCurve b_curve_node(b_node);
|
|
BL::CurveMapping mapping(b_curve_node.mapping());
|
|
RGBCurvesNode *curves = new RGBCurvesNode();
|
|
curvemapping_color_to_array(mapping,
|
|
curves->curves,
|
|
RAMP_TABLE_SIZE,
|
|
true);
|
|
curvemapping_minmax(mapping, true, &curves->min_x, &curves->max_x);
|
|
node = curves;
|
|
}
|
|
if(b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
|
|
BL::ShaderNodeVectorCurve b_curve_node(b_node);
|
|
BL::CurveMapping mapping(b_curve_node.mapping());
|
|
VectorCurvesNode *curves = new VectorCurvesNode();
|
|
curvemapping_color_to_array(mapping,
|
|
curves->curves,
|
|
RAMP_TABLE_SIZE,
|
|
false);
|
|
curvemapping_minmax(mapping, false, &curves->min_x, &curves->max_x);
|
|
node = curves;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeValToRGB)) {
|
|
RGBRampNode *ramp = new RGBRampNode();
|
|
BL::ShaderNodeValToRGB b_ramp_node(b_node);
|
|
BL::ColorRamp b_color_ramp(b_ramp_node.color_ramp());
|
|
colorramp_to_array(b_color_ramp, ramp->ramp, ramp->ramp_alpha, RAMP_TABLE_SIZE);
|
|
ramp->interpolate = b_color_ramp.interpolation() != BL::ColorRamp::interpolation_CONSTANT;
|
|
node = ramp;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeRGB)) {
|
|
ColorNode *color = new ColorNode();
|
|
color->value = get_node_output_rgba(b_node, "Color");
|
|
node = color;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeValue)) {
|
|
ValueNode *value = new ValueNode();
|
|
value->value = get_node_output_value(b_node, "Value");
|
|
node = value;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeCameraData)) {
|
|
node = new CameraNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeInvert)) {
|
|
node = new InvertNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeGamma)) {
|
|
node = new GammaNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBrightContrast)) {
|
|
node = new BrightContrastNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeMixRGB)) {
|
|
BL::ShaderNodeMixRGB b_mix_node(b_node);
|
|
MixNode *mix = new MixNode();
|
|
mix->type = (NodeMix)b_mix_node.blend_type();
|
|
mix->use_clamp = b_mix_node.use_clamp();
|
|
node = mix;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
|
|
node = new SeparateRGBNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeCombineRGB)) {
|
|
node = new CombineRGBNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeSeparateHSV)) {
|
|
node = new SeparateHSVNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeCombineHSV)) {
|
|
node = new CombineHSVNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeSeparateXYZ)) {
|
|
node = new SeparateXYZNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeCombineXYZ)) {
|
|
node = new CombineXYZNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeHueSaturation)) {
|
|
node = new HSVNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
|
|
node = new RGBToBWNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeMath)) {
|
|
BL::ShaderNodeMath b_math_node(b_node);
|
|
MathNode *math = new MathNode();
|
|
math->type = (NodeMath)b_math_node.operation();
|
|
math->use_clamp = b_math_node.use_clamp();
|
|
node = math;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeVectorMath)) {
|
|
BL::ShaderNodeVectorMath b_vector_math_node(b_node);
|
|
VectorMathNode *vmath = new VectorMathNode();
|
|
vmath->type = (NodeVectorMath)b_vector_math_node.operation();
|
|
node = vmath;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeVectorTransform)) {
|
|
BL::ShaderNodeVectorTransform b_vector_transform_node(b_node);
|
|
VectorTransformNode *vtransform = new VectorTransformNode();
|
|
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();
|
|
node = vtransform;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeNormal)) {
|
|
BL::Node::outputs_iterator out_it;
|
|
b_node.outputs.begin(out_it);
|
|
|
|
NormalNode *norm = new NormalNode();
|
|
norm->direction = get_node_output_vector(b_node, "Normal");
|
|
node = norm;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeMapping)) {
|
|
BL::ShaderNodeMapping b_mapping_node(b_node);
|
|
MappingNode *mapping = new MappingNode();
|
|
|
|
get_tex_mapping(&mapping->tex_mapping, b_mapping_node);
|
|
|
|
node = mapping;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeFresnel)) {
|
|
node = new FresnelNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeLayerWeight)) {
|
|
node = new LayerWeightNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeAddShader)) {
|
|
node = new AddClosureNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeMixShader)) {
|
|
node = new MixClosureNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeAttribute)) {
|
|
BL::ShaderNodeAttribute b_attr_node(b_node);
|
|
AttributeNode *attr = new AttributeNode();
|
|
attr->attribute = b_attr_node.attribute_name();
|
|
node = attr;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBackground)) {
|
|
node = new BackgroundNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeHoldout)) {
|
|
node = new HoldoutNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
|
|
BL::ShaderNodeBsdfAnisotropic b_aniso_node(b_node);
|
|
AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode();
|
|
|
|
switch(b_aniso_node.distribution()) {
|
|
case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
|
|
aniso->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
|
|
aniso->distribution = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfAnisotropic::distribution_MULTI_GGX:
|
|
aniso->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY:
|
|
aniso->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
|
|
break;
|
|
}
|
|
|
|
node = aniso;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
|
|
node = new DiffuseBsdfNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) {
|
|
BL::ShaderNodeSubsurfaceScattering b_subsurface_node(b_node);
|
|
|
|
SubsurfaceScatteringNode *subsurface = new SubsurfaceScatteringNode();
|
|
|
|
switch(b_subsurface_node.falloff()) {
|
|
case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
|
|
subsurface->falloff = CLOSURE_BSSRDF_CUBIC_ID;
|
|
break;
|
|
case BL::ShaderNodeSubsurfaceScattering::falloff_GAUSSIAN:
|
|
subsurface->falloff = CLOSURE_BSSRDF_GAUSSIAN_ID;
|
|
break;
|
|
case BL::ShaderNodeSubsurfaceScattering::falloff_BURLEY:
|
|
subsurface->falloff = CLOSURE_BSSRDF_BURLEY_ID;
|
|
break;
|
|
}
|
|
|
|
node = subsurface;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
|
|
BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
|
|
GlossyBsdfNode *glossy = new GlossyBsdfNode();
|
|
|
|
switch(b_glossy_node.distribution()) {
|
|
case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
|
|
glossy->distribution = CLOSURE_BSDF_REFLECTION_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
|
|
glossy->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfGlossy::distribution_GGX:
|
|
glossy->distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfGlossy::distribution_ASHIKHMIN_SHIRLEY:
|
|
glossy->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfGlossy::distribution_MULTI_GGX:
|
|
glossy->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
|
|
break;
|
|
}
|
|
node = glossy;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfGlass)) {
|
|
BL::ShaderNodeBsdfGlass b_glass_node(b_node);
|
|
GlassBsdfNode *glass = new GlassBsdfNode();
|
|
switch(b_glass_node.distribution()) {
|
|
case BL::ShaderNodeBsdfGlass::distribution_SHARP:
|
|
glass->distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
|
|
glass->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfGlass::distribution_GGX:
|
|
glass->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfGlass::distribution_MULTI_GGX:
|
|
glass->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
|
break;
|
|
}
|
|
node = glass;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) {
|
|
BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
|
|
RefractionBsdfNode *refraction = new RefractionBsdfNode();
|
|
switch(b_refraction_node.distribution()) {
|
|
case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
|
|
refraction->distribution = CLOSURE_BSDF_REFRACTION_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
|
|
refraction->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfRefraction::distribution_GGX:
|
|
refraction->distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
|
break;
|
|
}
|
|
node = refraction;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfToon)) {
|
|
BL::ShaderNodeBsdfToon b_toon_node(b_node);
|
|
ToonBsdfNode *toon = new ToonBsdfNode();
|
|
switch(b_toon_node.component()) {
|
|
case BL::ShaderNodeBsdfToon::component_DIFFUSE:
|
|
toon->component = CLOSURE_BSDF_DIFFUSE_TOON_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfToon::component_GLOSSY:
|
|
toon->component = CLOSURE_BSDF_GLOSSY_TOON_ID;
|
|
break;
|
|
}
|
|
node = toon;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfHair)) {
|
|
BL::ShaderNodeBsdfHair b_hair_node(b_node);
|
|
HairBsdfNode *hair = new HairBsdfNode();
|
|
switch(b_hair_node.component()) {
|
|
case BL::ShaderNodeBsdfHair::component_Reflection:
|
|
hair->component = CLOSURE_BSDF_HAIR_REFLECTION_ID;
|
|
break;
|
|
case BL::ShaderNodeBsdfHair::component_Transmission:
|
|
hair->component = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
|
|
break;
|
|
}
|
|
node = hair;
|
|
}
|
|
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;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
|
|
node = new TranslucentBsdfNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) {
|
|
node = new TransparentBsdfNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) {
|
|
node = new VelvetBsdfNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeEmission)) {
|
|
node = new EmissionNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
|
|
node = new AmbientOcclusionNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
|
|
node = new ScatterVolumeNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
|
|
node = new AbsorptionVolumeNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
|
|
node = new GeometryNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeWireframe)) {
|
|
BL::ShaderNodeWireframe b_wireframe_node(b_node);
|
|
WireframeNode *wire = new WireframeNode();
|
|
wire->use_pixel_size = b_wireframe_node.use_pixel_size();
|
|
node = wire;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeWavelength)) {
|
|
node = new WavelengthNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBlackbody)) {
|
|
node = new BlackbodyNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeLightPath)) {
|
|
node = new LightPathNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeLightFalloff)) {
|
|
node = new LightFalloffNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeObjectInfo)) {
|
|
node = new ObjectInfoNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeParticleInfo)) {
|
|
node = new ParticleInfoNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeHairInfo)) {
|
|
node = new HairInfoNode();
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeBump)) {
|
|
BL::ShaderNodeBump b_bump_node(b_node);
|
|
BumpNode *bump = new BumpNode();
|
|
bump->invert = b_bump_node.invert();
|
|
node = bump;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeScript)) {
|
|
#ifdef WITH_OSL
|
|
if(scene->shader_manager->use_osl()) {
|
|
/* create script node */
|
|
BL::ShaderNodeScript b_script_node(b_node);
|
|
|
|
OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager;
|
|
string bytecode_hash = b_script_node.bytecode_hash();
|
|
|
|
if(!bytecode_hash.empty()) {
|
|
node = manager->osl_node("", bytecode_hash, b_script_node.bytecode());
|
|
}
|
|
else {
|
|
string absolute_filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath());
|
|
node = manager->osl_node(absolute_filepath, "");
|
|
}
|
|
}
|
|
#else
|
|
(void)b_data;
|
|
(void)b_ntree;
|
|
#endif
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexImage)) {
|
|
BL::ShaderNodeTexImage b_image_node(b_node);
|
|
BL::Image b_image(b_image_node.image());
|
|
BL::ImageUser b_image_user(b_image_node.image_user());
|
|
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 ||
|
|
b_image.source() == BL::Image::source_MOVIE ||
|
|
(b_engine.is_preview() &&
|
|
b_image.source() != BL::Image::source_SEQUENCE);
|
|
|
|
if(is_builtin) {
|
|
/* for builtin images we're using image datablock name to find an image to
|
|
* read pixels from later
|
|
*
|
|
* also store frame number as well, so there's no differences in handling
|
|
* builtin names for packed images and movies
|
|
*/
|
|
int scene_frame = b_scene.frame_current();
|
|
int image_frame = image_user_frame_number(b_image_user,
|
|
scene_frame);
|
|
image->filename = b_image.name() + "@" + string_printf("%d", image_frame);
|
|
image->builtin_data = b_image.ptr.data;
|
|
}
|
|
else {
|
|
image->filename = image_user_file_path(b_image_user,
|
|
b_image,
|
|
b_scene.frame_current());
|
|
image->builtin_data = NULL;
|
|
}
|
|
|
|
image->animated = b_image_node.image_user().use_auto_refresh();
|
|
image->use_alpha = b_image.use_alpha();
|
|
|
|
/* TODO(sergey): Does not work properly when we change builtin type. */
|
|
if(b_image.is_updated()) {
|
|
scene->image_manager->tag_reload_image(
|
|
image->filename.string(),
|
|
image->builtin_data,
|
|
get_image_interpolation(b_image_node),
|
|
get_image_extension(b_image_node),
|
|
image->use_alpha);
|
|
}
|
|
}
|
|
image->color_space = (NodeImageColorSpace)b_image_node.color_space();
|
|
image->projection = (NodeImageProjection)b_image_node.projection();
|
|
image->interpolation = get_image_interpolation(b_image_node);
|
|
image->extension = get_image_extension(b_image_node);
|
|
image->projection_blend = b_image_node.projection_blend();
|
|
BL::TexMapping b_texture_mapping(b_image_node.texture_mapping());
|
|
get_tex_mapping(&image->tex_mapping, b_texture_mapping);
|
|
node = image;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexEnvironment)) {
|
|
BL::ShaderNodeTexEnvironment b_env_node(b_node);
|
|
BL::Image b_image(b_env_node.image());
|
|
BL::ImageUser b_image_user(b_env_node.image_user());
|
|
EnvironmentTextureNode *env = new EnvironmentTextureNode();
|
|
if(b_image) {
|
|
bool is_builtin = b_image.packed_file() ||
|
|
b_image.source() == BL::Image::source_GENERATED ||
|
|
b_image.source() == BL::Image::source_MOVIE ||
|
|
(b_engine.is_preview() &&
|
|
b_image.source() != BL::Image::source_SEQUENCE);
|
|
|
|
if(is_builtin) {
|
|
int scene_frame = b_scene.frame_current();
|
|
int image_frame = image_user_frame_number(b_image_user,
|
|
scene_frame);
|
|
env->filename = b_image.name() + "@" + string_printf("%d", image_frame);
|
|
env->builtin_data = b_image.ptr.data;
|
|
}
|
|
else {
|
|
env->filename = image_user_file_path(b_image_user,
|
|
b_image,
|
|
b_scene.frame_current());
|
|
env->builtin_data = NULL;
|
|
}
|
|
|
|
env->animated = b_env_node.image_user().use_auto_refresh();
|
|
env->use_alpha = b_image.use_alpha();
|
|
|
|
/* TODO(sergey): Does not work properly when we change builtin type. */
|
|
if(b_image.is_updated()) {
|
|
scene->image_manager->tag_reload_image(
|
|
env->filename.string(),
|
|
env->builtin_data,
|
|
get_image_interpolation(b_env_node),
|
|
EXTENSION_REPEAT,
|
|
env->use_alpha);
|
|
}
|
|
}
|
|
env->color_space = (NodeImageColorSpace)b_env_node.color_space();
|
|
env->interpolation = get_image_interpolation(b_env_node);
|
|
env->projection = (NodeEnvironmentProjection)b_env_node.projection();
|
|
BL::TexMapping b_texture_mapping(b_env_node.texture_mapping());
|
|
get_tex_mapping(&env->tex_mapping, b_texture_mapping);
|
|
node = env;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexGradient)) {
|
|
BL::ShaderNodeTexGradient b_gradient_node(b_node);
|
|
GradientTextureNode *gradient = new GradientTextureNode();
|
|
gradient->type = (NodeGradientType)b_gradient_node.gradient_type();
|
|
BL::TexMapping b_texture_mapping(b_gradient_node.texture_mapping());
|
|
get_tex_mapping(&gradient->tex_mapping, b_texture_mapping);
|
|
node = gradient;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
|
|
BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
|
|
VoronoiTextureNode *voronoi = new VoronoiTextureNode();
|
|
voronoi->coloring = (NodeVoronoiColoring)b_voronoi_node.coloring();
|
|
BL::TexMapping b_texture_mapping(b_voronoi_node.texture_mapping());
|
|
get_tex_mapping(&voronoi->tex_mapping, b_texture_mapping);
|
|
node = voronoi;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexMagic)) {
|
|
BL::ShaderNodeTexMagic b_magic_node(b_node);
|
|
MagicTextureNode *magic = new MagicTextureNode();
|
|
magic->depth = b_magic_node.turbulence_depth();
|
|
BL::TexMapping b_texture_mapping(b_magic_node.texture_mapping());
|
|
get_tex_mapping(&magic->tex_mapping, b_texture_mapping);
|
|
node = magic;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexWave)) {
|
|
BL::ShaderNodeTexWave b_wave_node(b_node);
|
|
WaveTextureNode *wave = new WaveTextureNode();
|
|
wave->type = (NodeWaveType)b_wave_node.wave_type();
|
|
wave->profile = (NodeWaveProfile)b_wave_node.wave_profile();
|
|
BL::TexMapping b_texture_mapping(b_wave_node.texture_mapping());
|
|
get_tex_mapping(&wave->tex_mapping, b_texture_mapping);
|
|
node = wave;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexChecker)) {
|
|
BL::ShaderNodeTexChecker b_checker_node(b_node);
|
|
CheckerTextureNode *checker = new CheckerTextureNode();
|
|
BL::TexMapping b_texture_mapping(b_checker_node.texture_mapping());
|
|
get_tex_mapping(&checker->tex_mapping, b_texture_mapping);
|
|
node = checker;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexBrick)) {
|
|
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();
|
|
BL::TexMapping b_texture_mapping(b_brick_node.texture_mapping());
|
|
get_tex_mapping(&brick->tex_mapping, b_texture_mapping);
|
|
node = brick;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexNoise)) {
|
|
BL::ShaderNodeTexNoise b_noise_node(b_node);
|
|
NoiseTextureNode *noise = new NoiseTextureNode();
|
|
BL::TexMapping b_texture_mapping(b_noise_node.texture_mapping());
|
|
get_tex_mapping(&noise->tex_mapping, b_texture_mapping);
|
|
node = noise;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
|
|
BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
|
|
MusgraveTextureNode *musgrave = new MusgraveTextureNode();
|
|
musgrave->type = (NodeMusgraveType)b_musgrave_node.musgrave_type();
|
|
BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping());
|
|
get_tex_mapping(&musgrave->tex_mapping, b_texture_mapping);
|
|
node = musgrave;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexCoord)) {
|
|
BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
|
|
TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
|
|
tex_coord->from_dupli = b_tex_coord_node.from_dupli();
|
|
if(b_tex_coord_node.object()) {
|
|
tex_coord->use_transform = true;
|
|
tex_coord->ob_tfm = get_transform(b_tex_coord_node.object().matrix_world());
|
|
}
|
|
node = tex_coord;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeTexSky)) {
|
|
BL::ShaderNodeTexSky b_sky_node(b_node);
|
|
SkyTextureNode *sky = new SkyTextureNode();
|
|
sky->type = (NodeSkyType)b_sky_node.sky_type();
|
|
sky->sun_direction = normalize(get_float3(b_sky_node.sun_direction()));
|
|
sky->turbidity = b_sky_node.turbidity();
|
|
sky->ground_albedo = b_sky_node.ground_albedo();
|
|
BL::TexMapping b_texture_mapping(b_sky_node.texture_mapping());
|
|
get_tex_mapping(&sky->tex_mapping, b_texture_mapping);
|
|
node = sky;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeNormalMap)) {
|
|
BL::ShaderNodeNormalMap b_normal_map_node(b_node);
|
|
NormalMapNode *nmap = new NormalMapNode();
|
|
nmap->space = (NodeNormalMapSpace)b_normal_map_node.space();
|
|
nmap->attribute = b_normal_map_node.uv_map();
|
|
node = nmap;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeTangent)) {
|
|
BL::ShaderNodeTangent b_tangent_node(b_node);
|
|
TangentNode *tangent = new TangentNode();
|
|
tangent->direction_type = (NodeTangentDirectionType)b_tangent_node.direction_type();
|
|
tangent->axis = (NodeTangentAxis)b_tangent_node.axis();
|
|
tangent->attribute = b_tangent_node.uv_map();
|
|
node = tangent;
|
|
}
|
|
else if(b_node.is_a(&RNA_ShaderNodeUVMap)) {
|
|
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;
|
|
}
|
|
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();
|
|
point_density->space = (NodeTexVoxelSpace)b_point_density_node.space();
|
|
point_density->interpolation = get_image_interpolation(b_point_density_node);
|
|
point_density->builtin_data = b_point_density_node.ptr.data;
|
|
|
|
/* 1 - render settings, 0 - vewport settings. */
|
|
int settings = background ? 1 : 0;
|
|
|
|
/* TODO(sergey): Use more proper update flag. */
|
|
if(true) {
|
|
b_point_density_node.cache_point_density(b_scene, settings);
|
|
scene->image_manager->tag_reload_image(
|
|
point_density->filename.string(),
|
|
point_density->builtin_data,
|
|
point_density->interpolation,
|
|
EXTENSION_CLIP,
|
|
true);
|
|
}
|
|
node = point_density;
|
|
|
|
/* 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;
|
|
point_density_texture_space(b_scene,
|
|
b_point_density_node,
|
|
settings,
|
|
loc,
|
|
size);
|
|
point_density->tfm =
|
|
transform_translate(-loc) * transform_scale(size) *
|
|
transform_inverse(get_transform(b_ob.matrix_world()));
|
|
}
|
|
}
|
|
|
|
if(node) {
|
|
node->name = b_node.name();
|
|
graph->add(node);
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
static bool node_use_modified_socket_name(ShaderNode *node)
|
|
{
|
|
if(node->special_type == SHADER_SPECIAL_TYPE_SCRIPT)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
static ShaderInput *node_find_input_by_name(ShaderNode *node,
|
|
BL::Node& b_node,
|
|
BL::NodeSocket& b_socket)
|
|
{
|
|
string name = b_socket.name();
|
|
|
|
if(node_use_modified_socket_name(node)) {
|
|
BL::Node::inputs_iterator b_input;
|
|
bool found = false;
|
|
int counter = 0, total = 0;
|
|
|
|
for(b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
|
|
if(b_input->name() == name) {
|
|
if(!found)
|
|
counter++;
|
|
total++;
|
|
}
|
|
|
|
if(b_input->ptr.data == b_socket.ptr.data)
|
|
found = true;
|
|
}
|
|
|
|
/* rename if needed */
|
|
if(name == "Shader")
|
|
name = "Closure";
|
|
|
|
if(total > 1)
|
|
name = string_printf("%s%d", name.c_str(), counter);
|
|
}
|
|
|
|
return node->input(name.c_str());
|
|
}
|
|
|
|
static ShaderOutput *node_find_output_by_name(ShaderNode *node,
|
|
BL::Node& b_node,
|
|
BL::NodeSocket& b_socket)
|
|
{
|
|
string name = b_socket.name();
|
|
|
|
if(node_use_modified_socket_name(node)) {
|
|
BL::Node::outputs_iterator b_output;
|
|
bool found = false;
|
|
int counter = 0, total = 0;
|
|
|
|
for(b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
|
|
if(b_output->name() == name) {
|
|
if(!found)
|
|
counter++;
|
|
total++;
|
|
}
|
|
|
|
if(b_output->ptr.data == b_socket.ptr.data)
|
|
found = true;
|
|
}
|
|
|
|
/* rename if needed */
|
|
if(name == "Shader")
|
|
name = "Closure";
|
|
|
|
if(total > 1)
|
|
name = string_printf("%s%d", name.c_str(), counter);
|
|
}
|
|
|
|
return node->output(name.c_str());
|
|
}
|
|
|
|
static void add_nodes(Scene *scene,
|
|
BL::RenderEngine& b_engine,
|
|
BL::BlendData& b_data,
|
|
BL::Scene& b_scene,
|
|
const bool background,
|
|
ShaderGraph *graph,
|
|
BL::ShaderNodeTree& b_ntree,
|
|
const ProxyMap &proxy_input_map,
|
|
const ProxyMap &proxy_output_map)
|
|
{
|
|
/* add nodes */
|
|
BL::ShaderNodeTree::nodes_iterator b_node;
|
|
PtrInputMap input_map;
|
|
PtrOutputMap output_map;
|
|
|
|
BL::Node::inputs_iterator b_input;
|
|
BL::Node::outputs_iterator b_output;
|
|
|
|
/* find the node to use for output if there are multiple */
|
|
bool found_active_output = false;
|
|
BL::ShaderNode output_node(PointerRNA_NULL);
|
|
|
|
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
|
|
if(is_output_node(*b_node)) {
|
|
BL::ShaderNodeOutputMaterial b_output_node(*b_node);
|
|
|
|
if(b_output_node.is_active_output()) {
|
|
output_node = b_output_node;
|
|
found_active_output = true;
|
|
break;
|
|
}
|
|
else if(!output_node.ptr.data && !found_active_output) {
|
|
output_node = b_output_node;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* add nodes */
|
|
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
|
|
if(b_node->mute() || b_node->is_a(&RNA_NodeReroute)) {
|
|
/* replace muted node with internal links */
|
|
BL::Node::internal_links_iterator b_link;
|
|
for(b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) {
|
|
BL::NodeSocket to_socket(b_link->to_socket());
|
|
SocketType::Type to_socket_type = convert_socket_type(to_socket);
|
|
ConvertNode *proxy = new ConvertNode(to_socket_type, to_socket_type, true);
|
|
|
|
input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
|
|
output_map[b_link->to_socket().ptr.data] = proxy->outputs[0];
|
|
|
|
graph->add(proxy);
|
|
}
|
|
}
|
|
else if(b_node->is_a(&RNA_ShaderNodeGroup) || b_node->is_a(&RNA_NodeCustomGroup)) {
|
|
|
|
BL::ShaderNodeTree b_group_ntree(PointerRNA_NULL);
|
|
if(b_node->is_a(&RNA_ShaderNodeGroup))
|
|
b_group_ntree = BL::ShaderNodeTree(((BL::NodeGroup)(*b_node)).node_tree());
|
|
else
|
|
b_group_ntree = BL::ShaderNodeTree(((BL::NodeCustomGroup)(*b_node)).node_tree());
|
|
ProxyMap group_proxy_input_map, group_proxy_output_map;
|
|
|
|
/* 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.
|
|
*/
|
|
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
|
|
SocketType::Type input_type = convert_socket_type(*b_input);
|
|
ConvertNode *proxy = new ConvertNode(input_type, input_type, true);
|
|
graph->add(proxy);
|
|
|
|
/* register the proxy node for internal binding */
|
|
group_proxy_input_map[b_input->identifier()] = proxy;
|
|
|
|
input_map[b_input->ptr.data] = proxy->inputs[0];
|
|
|
|
set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree);
|
|
}
|
|
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
|
|
SocketType::Type output_type = convert_socket_type(*b_output);
|
|
ConvertNode *proxy = new ConvertNode(output_type, output_type, true);
|
|
graph->add(proxy);
|
|
|
|
/* register the proxy node for internal binding */
|
|
group_proxy_output_map[b_output->identifier()] = proxy;
|
|
|
|
output_map[b_output->ptr.data] = proxy->outputs[0];
|
|
}
|
|
|
|
if(b_group_ntree) {
|
|
add_nodes(scene,
|
|
b_engine,
|
|
b_data,
|
|
b_scene,
|
|
background,
|
|
graph,
|
|
b_group_ntree,
|
|
group_proxy_input_map,
|
|
group_proxy_output_map);
|
|
}
|
|
}
|
|
else if(b_node->is_a(&RNA_NodeGroupInput)) {
|
|
/* map each socket to a proxy node */
|
|
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
|
|
ProxyMap::const_iterator proxy_it = proxy_input_map.find(b_output->identifier());
|
|
if(proxy_it != proxy_input_map.end()) {
|
|
ConvertNode *proxy = proxy_it->second;
|
|
|
|
output_map[b_output->ptr.data] = proxy->outputs[0];
|
|
}
|
|
}
|
|
}
|
|
else if(b_node->is_a(&RNA_NodeGroupOutput)) {
|
|
BL::NodeGroupOutput b_output_node(*b_node);
|
|
/* only the active group output is used */
|
|
if(b_output_node.is_active_output()) {
|
|
/* map each socket to a proxy node */
|
|
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
|
|
ProxyMap::const_iterator proxy_it = proxy_output_map.find(b_input->identifier());
|
|
if(proxy_it != proxy_output_map.end()) {
|
|
ConvertNode *proxy = proxy_it->second;
|
|
|
|
input_map[b_input->ptr.data] = proxy->inputs[0];
|
|
|
|
set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
ShaderNode *node = NULL;
|
|
|
|
if(is_output_node(*b_node)) {
|
|
if(b_node->ptr.data == output_node.ptr.data) {
|
|
node = graph->output();
|
|
}
|
|
}
|
|
else {
|
|
BL::ShaderNode b_shader_node(*b_node);
|
|
node = add_node(scene,
|
|
b_engine,
|
|
b_data,
|
|
b_scene,
|
|
background,
|
|
graph,
|
|
b_ntree,
|
|
b_shader_node);
|
|
}
|
|
|
|
if(node) {
|
|
/* map node sockets for linking */
|
|
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
|
|
ShaderInput *input = node_find_input_by_name(node, *b_node, *b_input);
|
|
if(!input) {
|
|
/* XXX should not happen, report error? */
|
|
continue;
|
|
}
|
|
input_map[b_input->ptr.data] = input;
|
|
|
|
set_default_value(input, *b_input, b_data, b_ntree);
|
|
}
|
|
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);
|
|
if(!output) {
|
|
/* XXX should not happen, report error? */
|
|
continue;
|
|
}
|
|
output_map[b_output->ptr.data] = output;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* connect nodes */
|
|
BL::NodeTree::links_iterator b_link;
|
|
|
|
for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
|
|
/* Ignore invalid links to avoid unwanted cycles created in graph. */
|
|
if(!b_link->is_valid()) {
|
|
continue;
|
|
}
|
|
/* get blender link data */
|
|
BL::NodeSocket b_from_sock = b_link->from_socket();
|
|
BL::NodeSocket b_to_sock = b_link->to_socket();
|
|
|
|
ShaderOutput *output = 0;
|
|
ShaderInput *input = 0;
|
|
|
|
PtrOutputMap::iterator output_it = output_map.find(b_from_sock.ptr.data);
|
|
if(output_it != output_map.end())
|
|
output = output_it->second;
|
|
PtrInputMap::iterator input_it = input_map.find(b_to_sock.ptr.data);
|
|
if(input_it != input_map.end())
|
|
input = input_it->second;
|
|
|
|
/* either node may be NULL when the node was not exported, typically
|
|
* because the node type is not supported */
|
|
if(output && input)
|
|
graph->connect(output, input);
|
|
}
|
|
}
|
|
|
|
static void add_nodes(Scene *scene,
|
|
BL::RenderEngine& b_engine,
|
|
BL::BlendData& b_data,
|
|
BL::Scene& b_scene,
|
|
const bool background,
|
|
ShaderGraph *graph,
|
|
BL::ShaderNodeTree& b_ntree)
|
|
{
|
|
static const ProxyMap empty_proxy_map;
|
|
add_nodes(scene,
|
|
b_engine,
|
|
b_data,
|
|
b_scene,
|
|
background,
|
|
graph,
|
|
b_ntree,
|
|
empty_proxy_map,
|
|
empty_proxy_map);
|
|
}
|
|
|
|
/* Sync Materials */
|
|
|
|
void BlenderSync::sync_materials(bool update_all)
|
|
{
|
|
shader_map.set_default(scene->default_surface);
|
|
|
|
/* material loop */
|
|
BL::BlendData::materials_iterator b_mat;
|
|
|
|
TaskPool pool;
|
|
set<Shader*> updated_shaders;
|
|
|
|
for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) {
|
|
Shader *shader;
|
|
|
|
/* test if we need to sync */
|
|
if(shader_map.sync(&shader, *b_mat) || update_all) {
|
|
ShaderGraph *graph = new ShaderGraph();
|
|
|
|
shader->name = b_mat->name().c_str();
|
|
shader->pass_id = b_mat->pass_index();
|
|
|
|
/* create nodes */
|
|
if(b_mat->use_nodes() && b_mat->node_tree()) {
|
|
BL::ShaderNodeTree b_ntree(b_mat->node_tree());
|
|
|
|
add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree);
|
|
}
|
|
else {
|
|
DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
|
|
diffuse->color = get_float3(b_mat->diffuse_color());
|
|
graph->add(diffuse);
|
|
|
|
ShaderNode *out = graph->output();
|
|
graph->connect(diffuse->output("BSDF"), out->input("Surface"));
|
|
}
|
|
|
|
/* settings */
|
|
PointerRNA cmat = RNA_pointer_get(&b_mat->ptr, "cycles");
|
|
shader->use_mis = get_boolean(cmat, "sample_as_light");
|
|
shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow");
|
|
shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume");
|
|
shader->volume_sampling_method = get_volume_sampling(cmat);
|
|
shader->volume_interpolation_method = get_volume_interpolation(cmat);
|
|
shader->displacement_method = (experimental) ? get_displacement_method(cmat) : DISPLACE_BUMP;
|
|
|
|
shader->set_graph(graph);
|
|
|
|
/* By simplifying the shader graph as soon as possible, some
|
|
* redundant shader nodes might be removed which prevents loading
|
|
* unnecessary attributes later.
|
|
*
|
|
* 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.
|
|
*/
|
|
if(!preview) {
|
|
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);
|
|
}
|
|
else {
|
|
/* NOTE: Update tagging can access links which are being
|
|
* optimized out.
|
|
*/
|
|
shader->tag_update(scene);
|
|
}
|
|
}
|
|
}
|
|
|
|
pool.wait_work();
|
|
|
|
foreach(Shader *shader, updated_shaders) {
|
|
shader->tag_update(scene);
|
|
}
|
|
}
|
|
|
|
/* Sync World */
|
|
|
|
void BlenderSync::sync_world(bool update_all)
|
|
{
|
|
Background *background = scene->background;
|
|
Background prevbackground = *background;
|
|
|
|
BL::World b_world = b_scene.world();
|
|
|
|
if(world_recalc || update_all || b_world.ptr.data != world_map) {
|
|
Shader *shader = scene->default_background;
|
|
ShaderGraph *graph = new ShaderGraph();
|
|
|
|
/* create nodes */
|
|
if(b_world && b_world.use_nodes() && b_world.node_tree()) {
|
|
BL::ShaderNodeTree b_ntree(b_world.node_tree());
|
|
|
|
add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree);
|
|
|
|
/* volume */
|
|
PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
|
|
shader->heterogeneous_volume = !get_boolean(cworld, "homogeneous_volume");
|
|
shader->volume_sampling_method = get_volume_sampling(cworld);
|
|
shader->volume_interpolation_method = get_volume_interpolation(cworld);
|
|
}
|
|
else if(b_world) {
|
|
BackgroundNode *background = new BackgroundNode();
|
|
background->color = get_float3(b_world.horizon_color());
|
|
graph->add(background);
|
|
|
|
ShaderNode *out = graph->output();
|
|
graph->connect(background->output("Background"), out->input("Surface"));
|
|
}
|
|
|
|
if(b_world) {
|
|
/* AO */
|
|
BL::WorldLighting b_light = b_world.light_settings();
|
|
|
|
if(b_light.use_ambient_occlusion())
|
|
background->ao_factor = b_light.ao_factor();
|
|
else
|
|
background->ao_factor = 0.0f;
|
|
|
|
background->ao_distance = b_light.distance();
|
|
|
|
/* 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;
|
|
visibility |= get_boolean(cvisibility, "scatter")? PATH_RAY_VOLUME_SCATTER: 0;
|
|
|
|
background->visibility = visibility;
|
|
}
|
|
else {
|
|
background->ao_factor = 0.0f;
|
|
background->ao_distance = FLT_MAX;
|
|
}
|
|
|
|
shader->set_graph(graph);
|
|
shader->tag_update(scene);
|
|
background->tag_update(scene);
|
|
}
|
|
|
|
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
|
|
|
/* when doing preview render check for BI's transparency settings,
|
|
* this is so because Blender's preview render routines are not able
|
|
* 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;
|
|
|
|
background->use_shader = render_layer.use_background_shader;
|
|
background->use_ao = render_layer.use_background_ao;
|
|
|
|
if(background->modified(prevbackground))
|
|
background->tag_update(scene);
|
|
}
|
|
|
|
/* Sync Lamps */
|
|
|
|
void BlenderSync::sync_lamps(bool update_all)
|
|
{
|
|
shader_map.set_default(scene->default_light);
|
|
|
|
/* lamp loop */
|
|
BL::BlendData::lamps_iterator b_lamp;
|
|
|
|
for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp) {
|
|
Shader *shader;
|
|
|
|
/* test if we need to sync */
|
|
if(shader_map.sync(&shader, *b_lamp) || update_all) {
|
|
ShaderGraph *graph = new ShaderGraph();
|
|
|
|
/* create nodes */
|
|
if(b_lamp->use_nodes() && b_lamp->node_tree()) {
|
|
shader->name = b_lamp->name().c_str();
|
|
|
|
BL::ShaderNodeTree b_ntree(b_lamp->node_tree());
|
|
|
|
add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree);
|
|
}
|
|
else {
|
|
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)
|
|
{
|
|
strength = 100.0f;
|
|
}
|
|
|
|
EmissionNode *emission = new EmissionNode();
|
|
emission->color = get_float3(b_lamp->color());
|
|
emission->strength = strength;
|
|
graph->add(emission);
|
|
|
|
ShaderNode *out = graph->output();
|
|
graph->connect(emission->output("Emission"), out->input("Surface"));
|
|
}
|
|
|
|
shader->set_graph(graph);
|
|
shader->tag_update(scene);
|
|
}
|
|
}
|
|
}
|
|
|
|
void BlenderSync::sync_shaders()
|
|
{
|
|
/* 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);
|
|
}
|
|
|
|
shader_map.pre_sync();
|
|
|
|
sync_world(auto_refresh_update);
|
|
sync_lamps(auto_refresh_update);
|
|
sync_materials(auto_refresh_update);
|
|
|
|
/* false = don't delete unused shaders, not supported */
|
|
shader_map.post_sync(false);
|
|
}
|
|
|
|
CCL_NAMESPACE_END
|
|
|