diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2017-04-18 17:30:13 +0300 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2017-04-18 17:30:13 +0300 |
commit | c9d78b6c434b5b1672ad0e0a2854eb9c1199f379 (patch) | |
tree | 47647ceb5a78cb951768bb03fbca0322e52fe2b2 /source | |
parent | bc6a75b405c4e0b1e85c9c6ec6646fd2d3f67686 (diff) | |
parent | 70018eb16e721f9171834afd4bf70dc017af1369 (diff) |
Merge remote-tracking branch 'origin/master' into blender2.8
Diffstat (limited to 'source')
50 files changed, 690 insertions, 178 deletions
diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc index 28e75db2862..e6a5b289c6b 100644 --- a/source/blender/alembic/intern/abc_curves.cc +++ b/source/blender/alembic/intern/abc_curves.cc @@ -95,7 +95,7 @@ void AbcCurveWriter::do_write() for (; nurbs; nurbs = nurbs->next) { if (nurbs->bp) { curve_basis = Alembic::AbcGeom::kNoBasis; - curve_type = Alembic::AbcGeom::kLinear; + curve_type = Alembic::AbcGeom::kVariableOrder; const int totpoint = nurbs->pntsu * nurbs->pntsv; @@ -160,7 +160,7 @@ void AbcCurveWriter::do_write() } } - orders.push_back(nurbs->orderu + 1); + orders.push_back(nurbs->orderu); vert_counts.push_back(verts.size()); } @@ -258,8 +258,8 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time) case Alembic::AbcGeom::kVariableOrder: if (orders && orders->size() > i) { nu->orderu = static_cast<short>((*orders)[i]); + break; } - break; case Alembic::AbcGeom::kLinear: default: nu->orderu = 2; diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc index ddbbf27392d..391f3fe79af 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -290,13 +290,7 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) OBox3dProperty archive_bounds_prop = Alembic::AbcGeom::CreateOArchiveBounds(m_writer->archive(), m_trans_sampling_index); - if (m_settings.flatten_hierarchy) { - createTransformWritersFlat(); - } - else { - createTransformWritersHierarchy(bmain->eval_ctx); - } - + createTransformWritersHierarchy(bmain->eval_ctx); createShapeWriters(bmain->eval_ctx); /* Make a list of frames to export. */ @@ -381,20 +375,6 @@ void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx) } } -void AbcExporter::createTransformWritersFlat() -{ - for (Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) { - Object *ob = base->object; - - if (export_object(&m_settings, base, false) && object_is_shape(ob)) { - std::string name = get_id_name(ob); - m_xforms[name] = new AbcTransformWriter( - ob, m_writer->archive().getTop(), NULL, - m_trans_sampling_index, m_settings); - } - } -} - void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, Object *parent, Object *dupliObParent) { Object *ob = ob_base->object; @@ -440,12 +420,18 @@ void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, O AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupliObParent) { - const std::string name = get_object_dag_path_name(ob, dupliObParent); - /* An object should not be its own parent, or we'll get infinite loops. */ BLI_assert(ob != parent); BLI_assert(ob != dupliObParent); + std::string name; + if (m_settings.flatten_hierarchy) { + name = get_id_name(ob); + } + else { + name = get_object_dag_path_name(ob, dupliObParent); + } + /* check if we have already created a transform writer for this object */ AbcTransformWriter *my_writer = getXForm(name); if (my_writer != NULL){ @@ -455,13 +441,23 @@ AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *pare AbcTransformWriter *parent_writer = NULL; Alembic::Abc::OObject alembic_parent; - if (parent) { + if (m_settings.flatten_hierarchy || parent == NULL) { + /* Parentless objects still have the "top object" as parent + * in Alembic. */ + alembic_parent = m_writer->archive().getTop(); + } + else { /* Since there are so many different ways to find parents (as evident * in the number of conditions below), we can't really look up the * parent by name. We'll just call createTransformWriter(), which will * return the parent's AbcTransformWriter pointer. */ if (parent->parent) { - parent_writer = createTransformWriter(parent, parent->parent, dupliObParent); + if (parent == dupliObParent) { + parent_writer = createTransformWriter(parent, parent->parent, NULL); + } + else { + parent_writer = createTransformWriter(parent, parent->parent, dupliObParent); + } } else if (parent == dupliObParent) { if (dupliObParent->parent == NULL) { @@ -478,14 +474,15 @@ AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *pare BLI_assert(parent_writer); alembic_parent = parent_writer->alembicXform(); } - else { - /* Parentless objects still have the "top object" as parent - * in Alembic. */ - alembic_parent = m_writer->archive().getTop(); - } my_writer = new AbcTransformWriter(ob, alembic_parent, parent_writer, m_trans_sampling_index, m_settings); + + /* When flattening, the matrix of the dupliobject has to be added. */ + if (m_settings.flatten_hierarchy && dupliObParent) { + my_writer->m_proxy_from = dupliObParent; + } + m_xforms[name] = my_writer; return my_writer; } diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h index f0e8e6b6815..75a2e0074f1 100644 --- a/source/blender/alembic/intern/abc_exporter.h +++ b/source/blender/alembic/intern/abc_exporter.h @@ -112,7 +112,6 @@ private: void getFrameSet(double step, std::set<double> &frames); void createTransformWritersHierarchy(EvaluationContext *eval_ctx); - void createTransformWritersFlat(); AbcTransformWriter * createTransformWriter(Object *ob, Object *parent, Object *dupliObParent); void exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, Object *parent, Object *dupliObParent); void exploreObject(EvaluationContext *eval_ctx, Base *ob_base, Object *dupliObParent); diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc index 2e626edeb8b..6e218cac429 100644 --- a/source/blender/alembic/intern/abc_transform.cc +++ b/source/blender/alembic/intern/abc_transform.cc @@ -62,6 +62,7 @@ AbcTransformWriter::AbcTransformWriter(Object *ob, unsigned int time_sampling, ExportSettings &settings) : AbcObjectWriter(NULL, ob, time_sampling, settings, parent) + , m_proxy_from(NULL) { m_is_animated = hasAnimation(m_object); @@ -90,7 +91,8 @@ void AbcTransformWriter::do_write() float yup_mat[4][4]; create_transform_matrix(m_object, yup_mat, - m_inherits_xform ? ABC_MATRIX_LOCAL : ABC_MATRIX_WORLD); + m_inherits_xform ? ABC_MATRIX_LOCAL : ABC_MATRIX_WORLD, + m_proxy_from); /* Only apply rotation to root camera, parenting will propagate it. */ if (m_object->type == OB_CAMERA && (!m_inherits_xform || !has_parent_camera(m_object))) { diff --git a/source/blender/alembic/intern/abc_transform.h b/source/blender/alembic/intern/abc_transform.h index 714adc299c1..59388e155dc 100644 --- a/source/blender/alembic/intern/abc_transform.h +++ b/source/blender/alembic/intern/abc_transform.h @@ -41,6 +41,9 @@ class AbcTransformWriter : public AbcObjectWriter { bool m_inherits_xform; public: + Object *m_proxy_from; + +public: AbcTransformWriter(Object *ob, const Alembic::AbcGeom::OObject &abc_parent, AbcTransformWriter *parent, diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc index 4b2541c23c4..24f77ad3a05 100644 --- a/source/blender/alembic/intern/abc_util.cc +++ b/source/blender/alembic/intern/abc_util.cc @@ -245,7 +245,8 @@ void convert_matrix(const Imath::M44d &xform, Object *ob, float r_mat[4][4]) /* Recompute transform matrix of object in new coordinate system * (from Z-Up to Y-Up). */ -void create_transform_matrix(Object *obj, float r_yup_mat[4][4], AbcMatrixMode mode) +void create_transform_matrix(Object *obj, float r_yup_mat[4][4], AbcMatrixMode mode, + Object *proxy_from) { float zup_mat[4][4]; @@ -255,11 +256,16 @@ void create_transform_matrix(Object *obj, float r_yup_mat[4][4], AbcMatrixMode m * constraints and modifiers as well as the obj->parentinv matrix. */ invert_m4_m4(obj->parent->imat, obj->parent->obmat); mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat); - copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP); } else { - copy_m44_axis_swap(r_yup_mat, obj->obmat, ABC_YUP_FROM_ZUP); + copy_m4_m4(zup_mat, obj->obmat); } + + if (proxy_from) { + mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat); + } + + copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP); } bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name) diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h index 9fdcf5e701b..4c6bd7d5412 100644 --- a/source/blender/alembic/intern/abc_util.h +++ b/source/blender/alembic/intern/abc_util.h @@ -62,7 +62,8 @@ typedef enum { ABC_MATRIX_WORLD = 1, ABC_MATRIX_LOCAL = 2, } AbcMatrixMode; -void create_transform_matrix(Object *obj, float r_transform_mat[4][4], AbcMatrixMode mode); +void create_transform_matrix(Object *obj, float r_transform_mat[4][4], + AbcMatrixMode mode, Object *proxy_from); void split(const std::string &s, const char delim, std::vector<std::string> &tokens); diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index c2323100205..a68f1e763fd 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -176,6 +176,7 @@ void BKE_pose_eval_bone(struct EvaluationContext *eval_ctx, struct bPoseChannel *pchan); void BKE_pose_constraints_evaluate(struct EvaluationContext *eval_ctx, + struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 7eb611d43a2..01d93d98540 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -792,6 +792,7 @@ struct ShadeResult; #define SH_NODE_OUTPUT_LINESTYLE 190 #define SH_NODE_UVALONGSTROKE 191 #define SH_NODE_TEX_POINTDENSITY 192 +#define SH_NODE_BSDF_PRINCIPLED 193 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 771790d417a..2a34a2e9418 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -621,10 +621,10 @@ void BKE_pose_eval_bone(struct EvaluationContext *UNUSED(eval_ctx), } void BKE_pose_constraints_evaluate(struct EvaluationContext *UNUSED(eval_ctx), + Scene *scene, Object *ob, bPoseChannel *pchan) { - Scene *scene = G.main->scene.first; DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name); bArmature *arm = (bArmature *)ob->data; if (arm->flag & ARM_RESTPOS) { diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 318f6480aaf..8a01e120d6d 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2216,8 +2216,10 @@ void BKE_imbuf_write_prepare(ImBuf *ibuf, const ImageFormatData *imf) ibuf->foptions.flag |= OPENEXR_HALF; ibuf->foptions.flag |= (imf->exr_codec & OPENEXR_COMPRESS); - if (!(imf->flag & R_IMF_FLAG_ZBUF)) - ibuf->zbuf_float = NULL; /* signal for exr saving */ + if (!(imf->flag & R_IMF_FLAG_ZBUF)) { + /* Signal for exr saving. */ + IMB_freezbuffloatImBuf(ibuf); + } } #endif diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 60c48bb5dd3..4b7dcc1b9b5 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3568,6 +3568,7 @@ static void registerShaderNodes(void) register_node_type_sh_background(); register_node_type_sh_bsdf_anisotropic(); register_node_type_sh_bsdf_diffuse(); + register_node_type_sh_bsdf_principled(); register_node_type_sh_bsdf_glossy(); register_node_type_sh_bsdf_glass(); register_node_type_sh_bsdf_translucent(); diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 668c94bec8a..9a70c42418f 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -64,6 +64,7 @@ #include "DEG_depsgraph.h" #include "BLI_strict_flags.h" +#include "BLI_hash.h" /* Dupli-Geometry */ @@ -180,6 +181,22 @@ static DupliObject *make_dupli(const DupliContext *ctx, if (ob->type == OB_MBALL) dob->no_draw = true; + /* random number */ + /* the logic here is designed to match Cycles */ + dob->random_id = BLI_hash_string(dob->ob->id.name + 2); + + if (dob->persistent_id[0] != INT_MAX) { + for(i = 0; i < MAX_DUPLI_RECUR*2; i++) + dob->random_id = BLI_hash_int_2d(dob->random_id, (unsigned int)dob->persistent_id[i]); + } + else { + dob->random_id = BLI_hash_int_2d(dob->random_id, 0); + } + + if (ctx->object != ob) { + dob->random_id ^= BLI_hash_int(BLI_hash_string(ctx->object->id.name + 2)); + } + return dob; } diff --git a/source/blender/blenlib/BLI_hash.h b/source/blender/blenlib/BLI_hash.h new file mode 100644 index 00000000000..50c7a7f9f0f --- /dev/null +++ b/source/blender/blenlib/BLI_hash.h @@ -0,0 +1,66 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_HASH_H__ +#define __BLI_HASH_H__ + +/** \file BLI_hash.h + * \ingroup bli + */ + +BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky) +{ +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + + unsigned int a, b, c; + + a = b = c = 0xdeadbeef + (2 << 2) + 13; + a += kx; + b += ky; + + c ^= b; c -= rot(b,14); + a ^= c; a -= rot(c,11); + b ^= a; b -= rot(a,25); + c ^= b; c -= rot(b,16); + a ^= c; a -= rot(c,4); + b ^= a; b -= rot(a,14); + c ^= b; c -= rot(b,24); + + return c; + +#undef rot +} + +BLI_INLINE unsigned int BLI_hash_string(const char *str) +{ + unsigned int i = 0, c; + + while((c = *str++)) + i = i * 37 + c; + + return i; +} + +BLI_INLINE unsigned int BLI_hash_int(unsigned int k) +{ + return BLI_hash_int_2d(k, 0); +} + +#endif // __BLI_HASH_H__ diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index b6a55d34d14..b59e7f99d59 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -44,7 +44,7 @@ void BLI_setenv_if_new(const char *env, const char *val) ATTR_NONNULL(1); void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file); void BLI_make_exist(char *dir); -void BLI_make_existing_file(const char *name); +bool BLI_make_existing_file(const char *name); void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen); void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen); void BLI_split_file_part(const char *string, char *file, const size_t filelen); diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 97225170f67..dc81ce000ea 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -152,6 +152,7 @@ set(SRC BLI_ghash.h BLI_graph.h BLI_gsqueue.h + BLI_hash.h BLI_hash_md5.h BLI_hash_mm2a.h BLI_heap.h diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 7b765cfa939..40b6aaa18c1 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1234,14 +1234,16 @@ void BLI_make_exist(char *dir) /** * Ensures that the parent directory of *name exists. + * + * \return true on success (i.e. given path now exists on FS), false otherwise. */ -void BLI_make_existing_file(const char *name) +bool BLI_make_existing_file(const char *name) { char di[FILE_MAX]; BLI_split_dir_part(name, di, sizeof(di)); /* make if the dir doesn't exist */ - BLI_dir_create_recursive(di); + return BLI_dir_create_recursive(di); } /** diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index d28aaf6a10a..b6279ed4217 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -130,7 +130,7 @@ struct DepsgraphNodeBuilder { void build_object(Scene *scene, Object *ob); void build_object_transform(Scene *scene, Object *ob); void build_object_constraints(Scene *scene, Object *ob); - void build_pose_constraints(Object *ob, bPoseChannel *pchan); + void build_pose_constraints(Scene *scene, Object *ob, bPoseChannel *pchan); void build_rigidbody(Scene *scene); void build_particles(Scene *scene, Object *ob); void build_cloth(Scene *scene, Object *object); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc index b1896fdc22a..ec5d1215d42 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc @@ -64,11 +64,12 @@ extern "C" { namespace DEG { -void DepsgraphNodeBuilder::build_pose_constraints(Object *ob, bPoseChannel *pchan) +void DepsgraphNodeBuilder::build_pose_constraints(Scene *scene, Object *ob, bPoseChannel *pchan) { /* create node for constraint stack */ add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, - DEPSOP_TYPE_EXEC, function_bind(BKE_pose_constraints_evaluate, _1, ob, pchan), + DEPSOP_TYPE_EXEC, + function_bind(BKE_pose_constraints_evaluate, _1, scene, ob, pchan), DEG_OPCODE_BONE_CONSTRAINTS); } @@ -201,7 +202,7 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob) /* constraints */ if (pchan->constraints.first != NULL) { - build_pose_constraints(ob, pchan); + build_pose_constraints(scene, ob, pchan); } /** diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 57805f92c8a..9e3344914bb 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -6049,6 +6049,9 @@ int join_curve_exec(bContext *C, wmOperator *op) cu = ob->data; BLI_movelisttolist(&cu->nurb, &tempbase); + /* Account for mixed 2D/3D curves when joining */ + BKE_curve_curve_dimension_update(cu); + DAG_relations_tag_update(bmain); // because we removed object(s), call before editmode! DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index c39516ff6ef..af557ec0872 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -486,7 +486,8 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, bGPdata *gpd = p->gpd; bGPDbrush *brush = p->brush; tGPspoint *pt; - + ToolSettings *ts = p->scene->toolsettings; + /* check painting mode */ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { /* straight lines only - i.e. only store start and end point in buffer */ @@ -638,7 +639,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, View3D *v3d = p->sa->spacedata.first; view3d_region_operator_needs_opengl(p->win, p->ar); - ED_view3d_autodist_init(p->scene, p->ar, v3d, (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 1 : 0); + ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0); } /* convert screen-coordinates to appropriate coordinates (and store them) */ @@ -758,7 +759,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) int i, totelem; /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */ - int depth_margin = (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 4 : 0; + int depth_margin = (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0; /* get total number of points to allocate space for * - drawing straight-lines only requires the endpoints @@ -912,7 +913,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) depth_arr[i] = 0.9999f; } else { - if (p->gpd->flag & GP_DATA_DEPTH_STROKE_ENDPOINTS) { + if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_ENDPOINTS) { /* remove all info between the valid endpoints */ int first_valid = 0; int last_valid = 0; @@ -1797,6 +1798,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) /* finish off a stroke (clears buffer, but doesn't finish the paint operation) */ static void gp_paint_strokeend(tGPsdata *p) { + ToolSettings *ts = p->scene->toolsettings; /* for surface sketching, need to set the right OpenGL context stuff so that * the conversions will project the values correctly... */ @@ -1805,7 +1807,7 @@ static void gp_paint_strokeend(tGPsdata *p) /* need to restore the original projection settings before packing up */ view3d_region_operator_needs_opengl(p->win, p->ar); - ED_view3d_autodist_init(p->scene, p->ar, v3d, (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 1 : 0); + ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0); } /* check if doing eraser or not */ diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index bb3375b91a6..fa613056df7 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -631,71 +631,63 @@ static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDom #define FLUID_SUFFIX_CONFIG_TMP (FLUID_SUFFIX_CONFIG ".tmp") #define FLUID_SUFFIX_SURFACE "fluidsurface" -static int fluid_init_filepaths(Object *fsDomain, char *targetDir, char *targetFile, char *debugStrBuffer) +static bool fluid_init_filepaths( + ReportList *reports, FluidsimSettings *domainSettings, Object *fsDomain, + char *targetDir, char *targetFile) { - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim); - FluidsimSettings *domainSettings= fluidmd->fss; - FILE *fileCfg; - int dirExist = 0; - char newSurfdataPath[FILE_MAX]; /* modified output settings */ const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP; - int outStringsChanged = 0; /* prepare names... */ - const char *relbase= modifier_path_relbase(fsDomain); + const char *relbase = modifier_path_relbase(fsDomain); + + /* We do not accept empty paths, they can end in random places silently, see T51176. */ + if (domainSettings->surfdataPath[0] == '\0') { + modifier_path_init(domainSettings->surfdataPath, sizeof(domainSettings->surfdataPath), + OB_FLUIDSIM_SURF_DIR_DEFAULT); + BKE_reportf(reports, RPT_WARNING, "Fluidsim: empty cache path, reset to default '%s'", + domainSettings->surfdataPath); + } BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR); - BLI_strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR); /* if 0'd out below, this value is never used! */ - BLI_path_abs(targetDir, relbase); /* fixed #frame-no */ + BLI_path_abs(targetDir, relbase); /* .tmp: don't overwrite/delete original file */ BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp); - // make sure all directories exist - // as the bobjs use the same dir, this only needs to be checked - // for the cfg output - BLI_make_existing_file(targetFile); - - // check selected directory - // simply try to open cfg file for writing to test validity of settings - fileCfg = BLI_fopen(targetFile, "w"); - if (fileCfg) { - dirExist = 1; fclose(fileCfg); - // remove cfg dummy from directory test - BLI_delete(targetFile, false, false); - } - - if (targetDir[0] == '\0' || (!dirExist)) { - char blendFile[FILE_MAX]; - - // invalid dir, reset to current/previous - BLI_split_file_part(G.main->name, blendFile, sizeof(blendFile)); - BLI_replace_extension(blendFile, FILE_MAX, ""); /* strip .blend */ - BLI_snprintf(newSurfdataPath, FILE_MAX, "//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name); - - BLI_snprintf(debugStrBuffer, 256, "fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath); - elbeemDebugOut(debugStrBuffer); - outStringsChanged=1; - } - - /* check if modified output dir is ok */ -#if 0 - if (outStringsChanged) { - char dispmsg[FILE_MAX+256]; - int selection=0; - BLI_strncpy(dispmsg, "Output settings set to: '", sizeof(dispmsg)); - strcat(dispmsg, newSurfdataPath); - strcat(dispmsg, "'%t|Continue with changed settings %x1|Discard and abort %x0"); - - /* ask user if thats what he/she wants... */ - selection = pupmenu(dispmsg); - if (selection < 1) return 0; /* 0 from menu, or -1 aborted */ - BLI_strncpy(targetDir, newSurfdataPath, sizeof(targetDir)); - strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR); - BLI_path_abs(targetDir, G.main->name); /* fixed #frame-no */ + /* Ensure whole path exists and is wirtable. */ + const bool dir_exists = BLI_dir_create_recursive(targetDir); + const bool is_writable = BLI_file_is_writable(targetFile); + + /* We change path to some presumably valid default value, but do not allow bake process to continue, + * this gives user chance to set manually another path. */ + if (!dir_exists || !is_writable) { + modifier_path_init(domainSettings->surfdataPath, sizeof(domainSettings->surfdataPath), + OB_FLUIDSIM_SURF_DIR_DEFAULT); + + if (!dir_exists) { + BKE_reportf(reports, RPT_ERROR, "Fluidsim: could not create cache directory '%s', reset to default '%s'", + targetDir, domainSettings->surfdataPath); + } + else { + BKE_reportf(reports, RPT_ERROR, "Fluidsim: cache directory '%s' is not writable, reset to default '%s'", + targetDir, domainSettings->surfdataPath); + } + + BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR); + BLI_path_abs(targetDir, relbase); + + /* .tmp: don't overwrite/delete original file */ + BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp); + + /* Ensure whole path exists and is wirtable. */ + if (!BLI_dir_create_recursive(targetDir) || !BLI_file_is_writable(targetFile)) { + BKE_reportf(reports, RPT_ERROR, "Fluidsim: could not use default cache directory '%s', " + "please define a valid cache path manually", targetDir); + } + return false; } -#endif - return outStringsChanged; + + return true; } /* ******************************************************************************** */ @@ -857,7 +849,6 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor char targetDir[FILE_MAX]; // store & modify output settings char targetFile[FILE_MAX]; // temp. store filename from targetDir for access - int outStringsChanged = 0; // modified? copy back before baking float domainMat[4][4]; float invDomMat[4][4]; @@ -943,7 +934,11 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor /* ******** prepare output file paths ******** */ - outStringsChanged = fluid_init_filepaths(fsDomain, targetDir, targetFile, debugStrBuffer); + if (!fluid_init_filepaths(reports, domainSettings, fsDomain, targetDir, targetFile)) { + fluidbake_free_data(channels, fobjects, fsset, fb); + return false; + } + channels->length = scene->r.efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra) channels->aniFrameTime = (double)((double)domainSettings->animEnd - (double)domainSettings->animStart) / (double)noFrames; @@ -968,11 +963,6 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor /* ******** start writing / exporting ******** */ // use .tmp, don't overwrite/delete original file BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixConfigTmp); - - // make sure these directories exist as well - if (outStringsChanged) { - BLI_make_existing_file(targetFile); - } /* ******** export domain to elbeem ******** */ elbeemResetSettings(fsset); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 54f620140bf..f4ed3c06328 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1184,6 +1184,7 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_BSDF_GLOSSY: case SH_NODE_BSDF_GLASS: case SH_NODE_BSDF_REFRACTION: + case SH_NODE_BSDF_PRINCIPLED: ntype->draw_buttons = node_shader_buts_glossy; break; case SH_NODE_BSDF_ANISOTROPIC: diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index cbcd6383a72..7d08e72bb7b 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -97,6 +97,7 @@ typedef enum GPUBuiltin { GPU_PARTICLE_ANG_VELOCITY = (1 << 12), GPU_LOC_TO_VIEW_MATRIX = (1 << 13), GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14), + GPU_OBJECT_INFO = (1 << 15) } GPUBuiltin; typedef enum GPUOpenGLBuiltin { @@ -212,6 +213,7 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link); void GPU_material_enable_alpha(GPUMaterial *material); +GPUBuiltin GPU_get_material_builtins(GPUMaterial *material); GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]); /* High level functions to create and use GPU materials */ @@ -228,7 +230,7 @@ void GPU_material_bind( float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock); void GPU_material_bind_uniforms( GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4], - float autobumpscale, GPUParticleInfo *pi); + float autobumpscale, GPUParticleInfo *pi, float object_info[3]); void GPU_material_unbind(GPUMaterial *material); bool GPU_material_bound(GPUMaterial *material); struct Scene *GPU_material_scene(GPUMaterial *material); @@ -325,6 +327,7 @@ struct GPUParticleInfo float location[3]; float velocity[3]; float angular_velocity[3]; + int random_id; }; #ifdef WITH_OPENSUBDIV diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index faf1b907570..de2b94482f4 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -410,6 +410,8 @@ const char *GPU_builtin_name(GPUBuiltin builtin) return "unfparticlevel"; else if (builtin == GPU_PARTICLE_ANG_VELOCITY) return "unfparticleangvel"; + else if (builtin == GPU_OBJECT_INFO) + return "unfobjectinfo"; else return ""; } diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index 79672b6d6e5..ef3ae4df9fe 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -826,7 +826,9 @@ bool GPU_fx_do_composite_pass( ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp); if (ssao_shader) { const GPUSSAOSettings *fx_ssao = fx->settings.ssao; - float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f}; + /* adjust attenuation to be scale invariant */ + float attenuation = fx_ssao->attenuation / (fx_ssao->distance_max * fx_ssao->distance_max); + float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, attenuation, 0.0f}; float sample_params[3]; sample_params[0] = fx->ssao_sample_count_cache; diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index ef23713c271..4115c115536 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -43,6 +43,7 @@ #include "BLI_math.h" #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLI_hash.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" @@ -1880,6 +1881,21 @@ static int gpu_get_particle_info(GPUParticleInfo *pi) return 0; } +static void GPU_get_object_info(float oi[3], Material *mat) +{ + Object *ob = GMS.gob; + oi[0] = ob->index; + oi[1] = mat->index; + unsigned int random; + if (GMS.dob) { + random = GMS.dob->random_id; + } + else { + random = BLI_hash_int_2d(BLI_hash_string(GMS.gob->id.name + 2), 0); + } + oi[2] = random * (1.0f/(float)0xFFFFFFFF); +} + int GPU_object_material_bind(int nr, void *attribs) { GPUVertexAttribs *gattribs = attribs; @@ -1939,21 +1955,27 @@ int GPU_object_material_bind(int nr, void *attribs) /* bind glsl material and get attributes */ Material *mat = GMS.gmatbuf[nr]; GPUParticleInfo partile_info; + float object_info[3] = {0}; float auto_bump_scale; GPUMaterial *gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv); GPU_material_vertex_attributes(gpumat, gattribs); - if (GMS.dob) + if (GMS.dob) { gpu_get_particle_info(&partile_info); + } + + if ((GPU_get_material_builtins(gpumat) & GPU_OBJECT_INFO) != 0) { + GPU_get_object_info(object_info, mat); + } GPU_material_bind( gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT), GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac, GMS.gscenelock); auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f; - GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info); + GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info, object_info); GMS.gboundmat = mat; /* for glsl use alpha blend mode, unless it's set to solid and diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index db5c3cf2f47..aa7a104ff86 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -124,6 +124,8 @@ struct GPUMaterial { int partvel; int partangvel; + int objectinfoloc; + ListBase lamps; bool bound; @@ -226,6 +228,8 @@ static int gpu_material_construct_end(GPUMaterial *material, const char *passnam material->partvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_VELOCITY)); if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) material->partangvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_ANG_VELOCITY)); + if (material->builtins & GPU_OBJECT_INFO) + material->objectinfoloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBJECT_INFO)); return 1; } else { @@ -346,9 +350,14 @@ void GPU_material_bind( } } +GPUBuiltin GPU_get_material_builtins(GPUMaterial *material) +{ + return material->builtins; +} + void GPU_material_bind_uniforms( GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4], - float autobumpscale, GPUParticleInfo *pi) + float autobumpscale, GPUParticleInfo *pi, float object_info[3]) { if (material->pass) { GPUShader *shader = GPU_pass_shader(material->pass); @@ -397,6 +406,9 @@ void GPU_material_bind_uniforms( if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) { GPU_shader_uniform_vector(shader, material->partangvel, 3, 1, pi->angular_velocity); } + if (material->builtins & GPU_OBJECT_INFO) { + GPU_shader_uniform_vector(shader, material->objectinfoloc, 3, 1, object_info); + } } } diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 737d186c950..26bfd70c025 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -35,10 +35,10 @@ #include "GPU_compositing.h" #include "GPU_extensions.h" +#include "GPU_matrix.h" #include "GPU_shader.h" -#include "GPU_uniformbuffer.h" #include "GPU_texture.h" -#include "GPU_matrix.h" +#include "GPU_uniformbuffer.h" #include "gpu_shader_private.h" diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl index 529132f85a9..6477390dca9 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl @@ -85,7 +85,7 @@ float calculate_ssao_factor(float depth) float f = dot(dir, normal); /* use minor bias here to avoid self shadowing */ - if (f > 0.05 * len + 0.0001) + if (f > 0.05 * len) factor += f * 1.0 / (len * (1.0 + len * len * ssao_params.z)); } } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index ef30f8ae6c5..857db4f7f7c 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2393,11 +2393,19 @@ void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol) /*********** NEW SHADER UTILITIES **************/ -float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) +float fresnel_dielectric_0(float eta) +{ + /* compute fresnel reflactance at normal incidence => cosi = 1.0 */ + float A = (eta - 1.0) / (eta + 1.0); + + return A * A; +} + +float fresnel_dielectric_cos(float cosi, float eta) { /* compute fresnel reflectance without explicitly computing * the refracted direction */ - float c = abs(dot(Incoming, Normal)); + float c = abs(cosi); float g = eta * eta - 1.0 + c * c; float result; @@ -2414,6 +2422,13 @@ float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) return result; } +float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) +{ + /* compute fresnel reflectance without explicitly computing + * the refracted direction */ + return fresnel_dielectric_cos(dot(Incoming, Normal), eta); +} + float hypot(float x, float y) { return sqrt(x * x + y * y); @@ -2507,6 +2522,57 @@ float floorfrac(float x, out int i) return x - i; } + +/* Principled BSDF operations */ + +float sqr(float a) +{ + return a*a; +} + +float schlick_fresnel(float u) +{ + float m = clamp(1.0 - u, 0.0, 1.0); + float m2 = m * m; + return m2 * m2 * m; // pow(m,5) +} + +float GTR1(float NdotH, float a) +{ + if (a >= 1.0) return M_1_PI; + float a2 = a*a; + float t = 1.0 + (a2 - 1.0) * NdotH*NdotH; + return (a2 - 1.0) / (M_PI * log(a2) * t); +} + +float GTR2(float NdotH, float a) +{ + float a2 = a*a; + float t = 1.0 + (a2 - 1.0) * NdotH*NdotH; + return a2 / (M_PI * t*t); +} + +float GTR2_aniso(float NdotH, float HdotX, float HdotY, float ax, float ay) +{ + return 1.0 / (M_PI * ax*ay * sqr(sqr(HdotX / ax) + sqr(HdotY / ay) + NdotH*NdotH)); +} + +float smithG_GGX(float NdotV, float alphaG) +{ + float a = alphaG*alphaG; + float b = NdotV*NdotV; + return 1.0 / (NdotV + sqrt(a + b - a * b)); +} + +vec3 rotate_vector(vec3 p, vec3 n, float theta) { + return ( + p * cos(theta) + cross(n, p) * + sin(theta) + n * dot(p, n) * + (1.0 - cos(theta)) + ); +} + + /*********** NEW SHADER NODES ***************/ #define NUM_LIGHTS 3 @@ -2568,6 +2634,126 @@ void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 resu node_bsdf_diffuse(color, 0.0, N, result); } +void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular, + float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat, + float clearcoat_gloss, float ior, float transparency, float refraction_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out vec4 result) +{ + /* ambient light */ + // TODO: set ambient light to an appropriate value + vec3 L = vec3(mix(0.1, 0.03, metallic)) * base_color.rgb; + + float eta = (2.0 / (1.0 - sqrt(0.08 * specular))) - 1.0; + + /* set the viewing vector */ + vec3 V = -normalize(I); + + /* get the tangent */ + vec3 Tangent = T; + if (T == vec3(0.0)) { + // if no tangent is set, use a default tangent + Tangent = vec3(1.0, 0.0, 0.0); + if (N.x != 0.0 || N.y != 0.0) { + vec3 N_xz = normalize(vec3(N.x, 0.0, N.z)); + + vec3 axis = normalize(cross(vec3(0.0, 0.0, 1.0), N_xz)); + float angle = acos(dot(vec3(0.0, 0.0, 1.0), N_xz)); + + Tangent = normalize(rotate_vector(vec3(1.0, 0.0, 0.0), axis, angle)); + } + } + + /* rotate tangent */ + if (anisotropic_rotation != 0.0) { + Tangent = rotate_vector(Tangent, N, anisotropic_rotation * 2.0 * M_PI); + } + + /* calculate the tangent and bitangent */ + vec3 Y = normalize(cross(N, Tangent)); + vec3 X = cross(Y, N); + + /* fresnel normalization parameters */ + float F0 = fresnel_dielectric_0(eta); + float F0_norm = 1.0 / (1.0 - F0); + + /* directional lights */ + for (int i = 0; i < NUM_LIGHTS; i++) { + vec3 light_position_world = gl_LightSource[i].position.xyz; + vec3 light_position = normalize(gl_NormalMatrix * light_position_world); + + vec3 H = normalize(light_position + V); + + vec3 light_specular = gl_LightSource[i].specular.rgb; + + float NdotL = dot(N, light_position); + float NdotV = dot(N, V); + float LdotH = dot(light_position, H); + + vec3 diffuse_and_specular_bsdf = vec3(0.0); + if (NdotL >= 0.0 && NdotV >= 0.0) { + float NdotH = dot(N, H); + + float Cdlum = 0.3 * base_color.r + 0.6 * base_color.g + 0.1 * base_color.b; // luminance approx. + + vec3 Ctint = Cdlum > 0 ? base_color.rgb / Cdlum : vec3(1.0); // normalize lum. to isolate hue+sat + vec3 Cspec0 = mix(specular * 0.08 * mix(vec3(1.0), Ctint, specular_tint), base_color.rgb, metallic); + vec3 Csheen = mix(vec3(1.0), Ctint, sheen_tint); + + // Diffuse fresnel - go from 1 at normal incidence to .5 at grazing + // and mix in diffuse retro-reflection based on roughness + + float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV); + float Fd90 = 0.5 + 2.0 * LdotH*LdotH * roughness; + float Fd = mix(1.0, Fd90, FL) * mix(1.0, Fd90, FV); + + // Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf + // 1.25 scale is used to (roughly) preserve albedo + // Fss90 used to "flatten" retroreflection based on roughness + float Fss90 = LdotH*LdotH * roughness; + float Fss = mix(1.0, Fss90, FL) * mix(1.0, Fss90, FV); + float ss = 1.25 * (Fss * (1.0 / (NdotL + NdotV) - 0.5) + 0.5); + + // specular + float aspect = sqrt(1.0 - anisotropic * 0.9); + float a = sqr(roughness); + float ax = max(0.001, a / aspect); + float ay = max(0.001, a * aspect); + float Ds = GTR2_aniso(NdotH, dot(H, X), dot(H, Y), ax, ay); //GTR2(NdotH, a); + float FH = (fresnel_dielectric_cos(LdotH, eta) - F0) * F0_norm; + vec3 Fs = mix(Cspec0, vec3(1.0), FH); + float roughg = sqr(roughness * 0.5 + 0.5); + float Gs = smithG_GGX(NdotL, roughg) * smithG_GGX(NdotV, roughg); + + // sheen + vec3 Fsheen = schlick_fresnel(LdotH) * sheen * Csheen; + + diffuse_and_specular_bsdf = (M_1_PI * mix(Fd, ss, subsurface) * base_color.rgb + Fsheen) + * (1.0 - metallic) + Gs * Fs * Ds; + } + diffuse_and_specular_bsdf *= max(NdotL, 0.0); + + float CNdotL = dot(CN, light_position); + float CNdotV = dot(CN, V); + + vec3 clearcoat_bsdf = vec3(0.0); + if (CNdotL >= 0.0 && CNdotV >= 0.0 && clearcoat > 0.0) { + float CNdotH = dot(CN, H); + //float FH = schlick_fresnel(LdotH); + + // clearcoat (ior = 1.5 -> F0 = 0.04) + float Dr = GTR1(CNdotH, mix(0.1, 0.001, clearcoat_gloss)); + float Fr = fresnel_dielectric_cos(LdotH, 1.5); //mix(0.04, 1.0, FH); + float Gr = smithG_GGX(CNdotL, 0.25) * smithG_GGX(CNdotV, 0.25); + + clearcoat_bsdf = clearcoat * Gr * Fr * Dr * vec3(0.25); + } + clearcoat_bsdf *= max(CNdotL, 0.0); + + L += light_specular * (diffuse_and_specular_bsdf + clearcoat_bsdf); + } + + result = vec4(L, 1.0); +} + void node_bsdf_translucent(vec4 color, vec3 N, out vec4 result) { node_bsdf_diffuse(color, 0.0, N, result); @@ -3578,12 +3764,12 @@ void node_light_falloff(float strength, float tsmooth, out float quadratic, out constant = strength; } -void node_object_info(out vec3 location, out float object_index, out float material_index, out float random) +void node_object_info(mat4 obmat, vec3 info, out vec3 location, out float object_index, out float material_index, out float random) { - location = vec3(0.0); - object_index = 0.0; - material_index = 0.0; - random = 0.0; + location = obmat[3].xyz; + object_index = info.x; + material_index = info.y; + random = info.z; } void node_normal_map(vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal) diff --git a/source/blender/makesdna/DNA_object_fluidsim.h b/source/blender/makesdna/DNA_object_fluidsim.h index a714195dd5d..846d5788d63 100644 --- a/source/blender/makesdna/DNA_object_fluidsim.h +++ b/source/blender/makesdna/DNA_object_fluidsim.h @@ -179,6 +179,7 @@ typedef struct FluidsimSettings { #define OB_FLUIDSIM_ACTIVE (1 << 1) #define OB_FLUIDSIM_OVERRIDE_TIME (1 << 2) +#define OB_FLUIDSIM_SURF_DIR_DEFAULT "cache_fluid" #define OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME "fluidsurface_preview_####.bobj.gz" #define OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME "fluidsurface_final_####.bobj.gz" #define OB_FLUIDSIM_SURF_FINAL_VEL_FNAME "fluidsurface_final_####.bvel.gz" diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 71d05e41c43..3045b5c3db5 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -342,6 +342,8 @@ typedef struct DupliObject { /* particle this dupli was generated from */ struct ParticleSystem *particle_system; + unsigned int random_id; + unsigned int pad; } DupliObject; /* **************** OBJECT ********************* */ diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 6ed2c55138c..a74758a4f71 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -342,7 +342,7 @@ static void rna_ID_user_clear(ID *id) static void rna_ID_user_remap(ID *id, Main *bmain, ID *new_id) { - if (GS(id->name) == GS(new_id->name)) { + if ((GS(id->name) == GS(new_id->name)) && (id != new_id)) { /* For now, do not allow remapping data in linked data from here... */ BKE_libblock_remap(bmain, id, new_id, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE); } diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 8d42d746e1c..c3477644979 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -2995,6 +2995,15 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p ED_node_tag_update_nodetree(bmain, ntree, node); } +static void rna_ShaderNodePrincipled_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNode *node = (bNode *)ptr->data; + + nodeUpdate(ntree, node); + rna_Node_update(bmain, scene, ptr); +} + static void rna_ShaderNodeSubsurface_update(Main *bmain, Scene *scene, PointerRNA *ptr) { bNodeTree *ntree = (bNodeTree *)ptr->id.data; @@ -3254,6 +3263,12 @@ static EnumPropertyItem node_script_mode_items[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem node_principled_distribution_items[] = { + { SHD_GLOSSY_GGX, "GGX", 0, "GGX", "" }, + { SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", "" }, + { 0, NULL, 0, NULL, NULL } +}; + /* -- Common nodes ---------------------------------------------------------- */ static void def_group_input(StructRNA *srna) @@ -4188,6 +4203,17 @@ static void def_glass(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_principled(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, node_principled_distribution_items); + RNA_def_property_ui_text(prop, "Distribution", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodePrincipled_update"); +} + static void def_refraction(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 1d92b0d7338..5b6046be57c 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2889,6 +2889,10 @@ static void rna_def_dupli_object(BlenderRNA *brna) RNA_def_property_enum_items(prop, dupli_items); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_ui_text(prop, "Dupli Type", "Duplicator type that generated this dupli object"); + + prop = RNA_def_property(srna, "random_id", PROP_INT, PROP_UNSIGNED); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Dupli random id", "Random id for this dupli object"); } static void rna_def_object_base_legacy(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 00e7447e843..feaf44acba0 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -379,49 +379,55 @@ static void rna_Object_ray_cast( float origin[3], float direction[3], float distance, int *r_success, float r_location[3], float r_normal[3], int *r_index) { - BVHTreeFromMesh treeData = {NULL}; - + bool success = false; + if (ob->derivedFinal == NULL) { BKE_reportf(reports, RPT_ERROR, "Object '%s' has no mesh data to be used for ray casting", ob->id.name + 2); return; } - /* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */ - bvhtree_from_mesh_looptri(&treeData, ob->derivedFinal, 0.0f, 4, 6); + /* Test BoundBox first (efficiency) */ + BoundBox *bb = BKE_object_boundbox_get(ob); + float distmin; + if (!bb || (isect_ray_aabb_v3_simple(origin, direction, bb->vec[0], bb->vec[6], &distmin, NULL) && distmin <= distance)) { - /* may fail if the mesh has no faces, in that case the ray-cast misses */ - if (treeData.tree != NULL) { - BVHTreeRayHit hit; + BVHTreeFromMesh treeData = {NULL}; - hit.index = -1; - hit.dist = distance; - - normalize_v3(direction); + /* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */ + bvhtree_from_mesh_looptri(&treeData, ob->derivedFinal, 0.0f, 4, 6); + + /* may fail if the mesh has no faces, in that case the ray-cast misses */ + if (treeData.tree != NULL) { + BVHTreeRayHit hit; + hit.index = -1; + hit.dist = distance; - if (BLI_bvhtree_ray_cast(treeData.tree, origin, direction, 0.0f, &hit, - treeData.raycast_callback, &treeData) != -1) - { - if (hit.dist <= distance) { - *r_success = true; + normalize_v3(direction); - copy_v3_v3(r_location, hit.co); - copy_v3_v3(r_normal, hit.no); - *r_index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[hit.index]); - goto finally; + if (BLI_bvhtree_ray_cast(treeData.tree, origin, direction, 0.0f, &hit, + treeData.raycast_callback, &treeData) != -1) + { + if (hit.dist <= distance) { + *r_success = success = true; + + copy_v3_v3(r_location, hit.co); + copy_v3_v3(r_normal, hit.no); + *r_index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[hit.index]); + } } + + free_bvhtree_from_mesh(&treeData); } } + if (success == false) { + *r_success = false; - *r_success = false; - - zero_v3(r_location); - zero_v3(r_normal); - *r_index = -1; - -finally: - free_bvhtree_from_mesh(&treeData); + zero_v3(r_location); + zero_v3(r_normal); + *r_index = -1; + } } static void rna_Object_closest_point_on_mesh( diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c index ffbbb1b0745..2ecf06057db 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim_util.c +++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c @@ -78,8 +78,8 @@ void fluidsim_init(FluidsimModifierData *fluidmd) fss->resolutionxyz = 65; fss->previewresxyz = 45; fss->realsize = 0.5; - fss->guiDisplayMode = 2; // preview - fss->renderDisplayMode = 3; // render + fss->guiDisplayMode = OB_FSDOM_PREVIEW; + fss->renderDisplayMode = OB_FSDOM_FINAL; fss->viscosityValue = 1.0; fss->viscosityExponent = 6; @@ -98,7 +98,7 @@ void fluidsim_init(FluidsimModifierData *fluidmd) /* fluid/inflow settings * fss->iniVel --> automatically set to 0 */ - modifier_path_init(fss->surfdataPath, sizeof(fss->surfdataPath), "cache_fluid"); + modifier_path_init(fss->surfdataPath, sizeof(fss->surfdataPath), OB_FLUIDSIM_SURF_DIR_DEFAULT); /* first init of bounding box */ /* no bounding box needed */ @@ -423,8 +423,6 @@ static void fluidsim_read_vel_cache(FluidsimModifierData *fluidmd, DerivedMesh * static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams) { - int displaymode = 0; - int curFrame = framenr /* - 1 */ /*scene->r.sfra*/; /* start with 0 at start frame */ /* why start with 0 as start frame?? Animations + time are frozen for frame 0 anyway. (See physics_fluid.c for that. - DG */ /* If we start with frame 0, we need to remap all animation channels, too, because they will all be 1 frame late if using frame-1! - DG */ @@ -435,25 +433,23 @@ static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, MPoly *mpoly; MPoly mp_example = {0}; - if (!useRenderParams) { - displaymode = fss->guiDisplayMode; - } - else { - displaymode = fss->renderDisplayMode; - } + const int displaymode = useRenderParams ? fss->renderDisplayMode : fss->guiDisplayMode; switch (displaymode) { - case 1: + case OB_FSDOM_GEOM: /* just display original object */ return NULL; - case 2: + case OB_FSDOM_PREVIEW: /* use preview mesh */ BLI_join_dirfile(targetFile, sizeof(targetFile), fss->surfdataPath, OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME); break; - default: /* 3 */ - /* 3. use final mesh */ + case OB_FSDOM_FINAL: + /* use final mesh */ BLI_join_dirfile(targetFile, sizeof(targetFile), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME); break; + default: + BLI_assert(!"Wrong fluidsim display type"); + return NULL; } /* offset baked frame */ @@ -494,7 +490,7 @@ static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, /* load vertex velocities, if they exist... * TODO? use generate flag as loading flag as well? * warning, needs original .bobj.gz mesh loading filename */ - if (displaymode == 3) { + if (displaymode == OB_FSDOM_FINAL) { fluidsim_read_vel_cache(fluidmd, dm, targetFile); } else { diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index d20881df150..3596a2aa12d 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -163,6 +163,7 @@ set(SRC shader/nodes/node_shader_background.c shader/nodes/node_shader_bsdf_anisotropic.c shader/nodes/node_shader_bsdf_diffuse.c + shader/nodes/node_shader_bsdf_principled.c shader/nodes/node_shader_bsdf_glass.c shader/nodes/node_shader_bsdf_glossy.c shader/nodes/node_shader_bsdf_toon.c diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 4c0047f1d58..804c1897a27 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -106,6 +106,7 @@ void register_node_type_sh_bsdf_transparent(void); void register_node_type_sh_bsdf_velvet(void); void register_node_type_sh_bsdf_toon(void); void register_node_type_sh_bsdf_anisotropic(void); +void register_node_type_sh_bsdf_principled(void); void register_node_type_sh_emission(void); void register_node_type_sh_holdout(void); void register_node_type_sh_volume_absorption(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index a9c0df7d7e8..e754d063397 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -80,6 +80,7 @@ DefNode( ShaderNode, SH_NODE_BACKGROUND, 0, "BA DefNode( ShaderNode, SH_NODE_HOLDOUT, 0, "HOLDOUT", Holdout, "Holdout", "" ) DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, def_anisotropic, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse BSDF", "" ) +DefNode( ShaderNode, SH_NODE_BSDF_PRINCIPLED, def_principled, "BSDF_PRINCIPLED", BsdfPrincipled, "Principled BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glass, "BSDF_GLASS", BsdfGlass, "Glass BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_refraction, "BSDF_REFRACTION", BsdfRefraction, "Refraction BSDF", "" ) diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c new file mode 100644 index 00000000000..8b0bfa36324 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c @@ -0,0 +1,114 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../node_shader_util.h" + +/* **************** OUTPUT ******************** */ + +static bNodeSocketTemplate sh_node_bsdf_principled_in[] = { + { SOCK_RGBA, 1, N_("Base Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Subsurface"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_VECTOR, 1, N_("Subsurface Radius"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f}, + { SOCK_RGBA, 1, N_("Subsurface Color"), 0.7f, 0.1f, 0.1f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Metallic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Specular"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Specular Tint"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Anisotropic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Anisotropic Rotation"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Sheen"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Sheen Tint"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Clearcoat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Clearcoat Gloss"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, + { SOCK_FLOAT, 1, N_("Transparency"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Refraction Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { SOCK_VECTOR, 1, N_("Clearcoat Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { SOCK_VECTOR, 1, N_("Tangent"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_bsdf_principled_out[] = { + { SOCK_SHADER, 0, N_("BSDF")}, + { -1, 0, "" } +}; + +static void node_shader_init_principled(bNodeTree *UNUSED(ntree), bNode *node) +{ + node->custom1 = SHD_GLOSSY_MULTI_GGX; +} + +static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + // normal + if (!in[17].link) + in[17].link = GPU_builtin(GPU_VIEW_NORMAL); + else + GPU_link(mat, "direction_transform_m4v3", in[17].link, GPU_builtin(GPU_VIEW_MATRIX), &in[17].link); + + // clearcoat normal + if (!in[18].link) + in[18].link = GPU_builtin(GPU_VIEW_NORMAL); + else + GPU_link(mat, "direction_transform_m4v3", in[18].link, GPU_builtin(GPU_VIEW_MATRIX), &in[18].link); + + return GPU_stack_link(mat, "node_bsdf_principled", in, out, GPU_builtin(GPU_VIEW_POSITION)); +} + +static void node_shader_update_principled(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sock; + int distribution = node->custom1; + + for (sock = node->inputs.first; sock; sock = sock->next) { + if (STREQ(sock->name, "Refraction Roughness")) { + if (distribution == SHD_GLOSSY_GGX) + sock->flag &= ~SOCK_UNAVAIL; + else + sock->flag |= SOCK_UNAVAIL; + + } + } +} + +/* node type definition */ +void register_node_type_sh_bsdf_principled(void) +{ + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_BSDF_PRINCIPLED, "Principled BSDF", NODE_CLASS_SHADER, 0); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_bsdf_principled_in, sh_node_bsdf_principled_out); + node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); + node_type_init(&ntype, node_shader_init_principled); + node_type_storage(&ntype, "", NULL, NULL); + node_type_gpu(&ntype, node_shader_gpu_bsdf_principled); + node_type_update(&ntype, node_shader_update_principled, NULL); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c index d1905246fd4..165d565a5b4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_object_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c @@ -39,7 +39,16 @@ static bNodeSocketTemplate sh_node_object_info_out[] = { static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, "node_object_info", in, out); + return GPU_stack_link(mat, "node_object_info", in, out, GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_OBJECT_INFO)); +} + +static void node_shader_exec_object_info(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out) +{ + ShaderCallData *scd = (ShaderCallData *)data; + copy_v4_v4(out[0]->vec, RE_object_instance_get_matrix(scd->shi->obi, RE_OBJECT_INSTANCE_MATRIX_OB)[3]); + out[1]->vec[0] = RE_object_instance_get_object_pass_index(scd->shi->obi); + out[2]->vec[0] = scd->shi->mat->index; + out[3]->vec[0] = RE_object_instance_get_random_id(scd->shi->obi) * (1.0f/(float)0xFFFFFFFF);; } /* node type definition */ @@ -53,6 +62,7 @@ void register_node_type_sh_object_info(void) node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); node_type_gpu(&ntype, node_shader_gpu_object_info); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_object_info); nodeRegisterType(&ntype); } diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index f535aa5aa71..eaa4cf2c69c 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -381,7 +381,7 @@ bool RE_allow_render_generic_object(struct Object *ob); /* RE_updateRenderInstances flag */ enum { RE_OBJECT_INSTANCES_UPDATE_VIEW = (1 << 0), - RE_OBJECT_INSTANCES_UPDATE_OBMAT = (1 << 1), + RE_OBJECT_INSTANCES_UPDATE_OBMAT = (1 << 1) }; void RE_updateRenderInstances(Render *re, int flag); diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index ae389fdfd2e..b64c0c8fc52 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -178,6 +178,7 @@ typedef struct ShadeInput { unsigned int lay; int layflag, passflag, combinedflag; + short object_pass_index; struct Group *light_override; struct Material *mat_override; @@ -241,6 +242,9 @@ enum { const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4]; +float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi); +float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi); + enum { RE_VIEW_MATRIX, RE_VIEWINV_MATRIX, diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index b3a5ccdae17..f0323340899 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -382,6 +382,8 @@ typedef struct ObjectInstanceRen { float part_co[3]; float part_vel[3]; float part_avel[3]; + + unsigned int random_id; } ObjectInstanceRen; /* ------------------------------------------------------------------------- */ diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 76e6ca8d467..199322795f3 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -66,6 +66,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_hash.h" #include "DNA_material_types.h" #include "DNA_meshdata_types.h" @@ -1458,6 +1459,14 @@ ObjectInstanceRen *RE_addRenderInstance( } } + /* Fill object info */ + if (dob) { + obi->random_id = dob->random_id; + } + else { + obi->random_id = BLI_hash_int_2d(BLI_hash_string(obi->ob->id.name + 2), 0); + } + RE_updateRenderInstance(re, obi, RE_OBJECT_INSTANCES_UPDATE_OBMAT | RE_OBJECT_INSTANCES_UPDATE_VIEW); if (mat) { diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index a8fb72fb7f8..8dea0930b9e 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -2141,6 +2141,16 @@ const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int m return NULL; } +float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi) +{ + return obi->ob->index; +} + +float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi) +{ + return obi->random_id; +} + const float (*RE_render_current_get_matrix(int matrix_id))[4] { switch (matrix_id) { diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index b57acc14d36..858e1de9176 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -278,6 +278,8 @@ struct Object *RE_GetCamera(struct Render *re) RET_NULL float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]) RET_ZERO const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4] RET_NULL const float (*RE_render_current_get_matrix(int matrix_id))[4] RET_NULL +float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi) RET_ZERO +float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi) RET_ZERO /* blenkernel */ bool BKE_paint_proj_mesh_data_check(struct Scene *scene, struct Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil) RET_ZERO diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 95679b5d3a6..9cbd61590b6 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -169,7 +169,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) rasty->GetViewMatrix().getValue(&viewmat[0][0]); float auto_bump_scale = ms.m_pDerivedMesh!=0 ? ms.m_pDerivedMesh->auto_bump_scale : 1.0f; - GPU_material_bind_uniforms(gpumat, obmat, viewmat, obcol, auto_bump_scale, NULL); + GPU_material_bind_uniforms(gpumat, obmat, viewmat, obcol, auto_bump_scale, NULL, NULL); mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol); } |