diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2019-08-13 01:11:36 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2019-08-14 14:36:56 +0300 |
commit | 13d469e6f0c554399629febeb1fd8d680b873a90 (patch) | |
tree | 16d8812da3b9cc1295a4693e1ec3e6687e1ae36f | |
parent | d5002f007e8d770dea15f0881cd9d0a4f3aaf824 (diff) |
Eevee: Remove Additive & Multiply Blend mode
This commit also provide a compatibility code that will convert old
materials using Additive or Multiply Blend mode to their node equivalent.
This conversion is only done on outputs that are enabled for eevee.
-rw-r--r-- | source/blender/blenkernel/BKE_blender_version.h | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 8 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.h | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_280.c | 186 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_materials.c | 15 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_material_types.h | 12 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_material.c | 10 |
7 files changed, 198 insertions, 37 deletions
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index ced9f4a3153..0c55ae8ee83 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ * \note Use #STRINGIFY() rather than defining with quotes. */ #define BLENDER_VERSION 281 -#define BLENDER_SUBVERSION 1 +#define BLENDER_SUBVERSION 2 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 65120fc4c10..bcee606ea7b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9487,7 +9487,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) /* don't forget to set version number in BKE_blender_version.h! */ } -static void do_versions_after_linking(Main *main) +static void do_versions_after_linking(Main *main, ReportList *reports) { // printf("%s for %s (%s), %d.%d\n", __func__, main->curlib ? main->curlib->name : main->name, // main->curlib ? "LIB" : "MAIN", main->versionfile, main->subversionfile); @@ -9495,7 +9495,7 @@ static void do_versions_after_linking(Main *main) do_versions_after_linking_250(main); do_versions_after_linking_260(main); do_versions_after_linking_270(main); - do_versions_after_linking_280(main); + do_versions_after_linking_280(main, reports); do_versions_after_linking_cycles(main); } @@ -9798,7 +9798,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) blo_split_main(&mainlist, bfd->main); for (Main *mainvar = mainlist.first; mainvar; mainvar = mainvar->next) { BLI_assert(mainvar->versionfile != 0); - do_versions_after_linking(mainvar); + do_versions_after_linking(mainvar, fd->reports); } blo_join_main(&mainlist); @@ -11569,7 +11569,7 @@ static void library_link_end(Main *mainl, * or they will go again through do_versions - bad, very bad! */ split_main_newid(mainvar, main_newid); - do_versions_after_linking(main_newid); + do_versions_after_linking(main_newid, (*fd)->reports); add_main_to_main(mainvar, main_newid); } diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index 7cd5bb7ac93..10ee3d52a74 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -187,7 +187,7 @@ void blo_do_versions_cycles(struct FileData *fd, struct Library *lib, struct Mai void do_versions_after_linking_250(struct Main *bmain); void do_versions_after_linking_260(struct Main *bmain); void do_versions_after_linking_270(struct Main *bmain); -void do_versions_after_linking_280(struct Main *bmain); +void do_versions_after_linking_280(struct Main *bmain, ReportList *reports); void do_versions_after_linking_cycles(struct Main *bmain); #endif diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 15b4f513050..254259b1542 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -734,7 +734,128 @@ static void do_versions_seq_alloc_transform_and_crop(ListBase *seqbase) } } -void do_versions_after_linking_280(Main *bmain) +/* Return true if there is something to convert. */ +static bool do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, + char blend_method, + GSet *nodegrp_tree_set) +{ + bool need_update = false; + bool do_conversion = false; + + /* Iterate backwards from end so we don't encounter newly added links. */ + bNodeLink *prevlink; + for (bNodeLink *link = ntree->links.last; link; link = prevlink) { + prevlink = link->prev; + + /* Detect link to replace. */ + bNode *fromnode = link->fromnode; + bNodeSocket *fromsock = link->fromsock; + bNode *tonode = link->tonode; + bNodeSocket *tosock = link->tosock; + + if (nodegrp_tree_set) { + if (fromnode->type == NODE_GROUP && fromnode->id != NULL) { + bNodeTree *group_ntree = (bNodeTree *)fromnode->id; + if (BLI_gset_add(nodegrp_tree_set, group_ntree)) { + /* Recursive but not convert (blend_method = -1). Conversion happens after. */ + if (!do_versions_material_convert_legacy_blend_mode(group_ntree, -1, nodegrp_tree_set)) { + /* There is no output to convert in the tree, remove it. */ + BLI_gset_remove(nodegrp_tree_set, group_ntree, NULL); + } + } + } + if (tonode->type == NODE_GROUP && tonode->id != NULL) { + bNodeTree *group_ntree = (bNodeTree *)tonode->id; + if (BLI_gset_add(nodegrp_tree_set, group_ntree)) { + /* Recursive but not convert (blend_method = -1). Conversion happens after. */ + if (!do_versions_material_convert_legacy_blend_mode(group_ntree, -1, nodegrp_tree_set)) { + /* There is no output to convert in the tree, remove it. */ + BLI_gset_remove(nodegrp_tree_set, group_ntree, NULL); + } + } + } + } + + if (!(tonode->type == SH_NODE_OUTPUT_MATERIAL && STREQ(tosock->identifier, "Surface"))) { + continue; + } + + /* Only do outputs that are enabled for EEVEE */ + if (!ELEM(tonode->custom1, SHD_OUTPUT_ALL, SHD_OUTPUT_EEVEE)) { + continue; + } + + do_conversion = true; + + if (blend_method == 1 /* MA_BM_ADD */) { + nodeRemLink(ntree, link); + + bNode *add_node = nodeAddStaticNode(NULL, ntree, SH_NODE_ADD_SHADER); + add_node->locx = 0.5f * (fromnode->locx + tonode->locx); + add_node->locy = 0.5f * (fromnode->locy + tonode->locy); + + bNodeSocket *shader1_socket = add_node->inputs.first; + bNodeSocket *shader2_socket = add_node->inputs.last; + bNodeSocket *add_socket = nodeFindSocket(add_node, SOCK_OUT, "Shader"); + + bNode *transp_node = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_TRANSPARENT); + transp_node->locx = add_node->locx; + transp_node->locy = add_node->locy - 110.0f; + + bNodeSocket *transp_socket = nodeFindSocket(transp_node, SOCK_OUT, "BSDF"); + + /* Link to input and material output node. */ + nodeAddLink(ntree, fromnode, fromsock, add_node, shader1_socket); + nodeAddLink(ntree, transp_node, transp_socket, add_node, shader2_socket); + nodeAddLink(ntree, add_node, add_socket, tonode, tosock); + + need_update = true; + } + else if (blend_method == 2 /* MA_BM_MULTIPLY */) { + nodeRemLink(ntree, link); + + bNode *transp_node = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_TRANSPARENT); + + bNodeSocket *color_socket = nodeFindSocket(transp_node, SOCK_IN, "Color"); + bNodeSocket *transp_socket = nodeFindSocket(transp_node, SOCK_OUT, "BSDF"); + + /* If incomming link is from a closure socket, we need to convert it. */ + if (fromsock->type == SOCK_SHADER) { + transp_node->locx = 0.33f * fromnode->locx + 0.66f * tonode->locx; + transp_node->locy = 0.33f * fromnode->locy + 0.66f * tonode->locy; + + bNode *shtorgb_node = nodeAddStaticNode(NULL, ntree, SH_NODE_SHADERTORGB); + shtorgb_node->locx = 0.66f * fromnode->locx + 0.33f * tonode->locx; + shtorgb_node->locy = 0.66f * fromnode->locy + 0.33f * tonode->locy; + + bNodeSocket *shader_socket = nodeFindSocket(shtorgb_node, SOCK_IN, "Shader"); + bNodeSocket *rgba_socket = nodeFindSocket(shtorgb_node, SOCK_OUT, "Color"); + + nodeAddLink(ntree, fromnode, fromsock, shtorgb_node, shader_socket); + nodeAddLink(ntree, shtorgb_node, rgba_socket, transp_node, color_socket); + } + else { + transp_node->locx = 0.5f * (fromnode->locx + tonode->locx); + transp_node->locy = 0.5f * (fromnode->locy + tonode->locy); + + nodeAddLink(ntree, fromnode, fromsock, transp_node, color_socket); + } + + /* Link to input and material output node. */ + nodeAddLink(ntree, transp_node, transp_socket, tonode, tosock); + + need_update = true; + } + } + + if (need_update) { + ntreeUpdateTree(NULL, ntree); + } + + return do_conversion; +} + +void do_versions_after_linking_280(Main *bmain, ReportList *reports) { bool use_collection_compat_28 = true; @@ -1129,6 +1250,69 @@ void do_versions_after_linking_280(Main *bmain) camera->dof_ob = NULL; } } + + if (!MAIN_VERSION_ATLEAST(bmain, 281, 2)) { + /* Replace Multiply and Additive blend mode by Alpha Blend + * now that we use dualsource blending. */ + /* We take care of doing only nodetrees that are always part of materials + * with old blending modes. */ + GSet *ntrees_additive = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + GSet *ntrees_multiply = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + GSet *ntrees_nolegacy = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + for (Material *ma = bmain->materials.first; ma; ma = ma->id.next) { + bNodeTree *ntree = ma->nodetree; + if (ma->blend_method == 1 /* MA_BM_ADD */) { + if (ma->use_nodes) { + do_versions_material_convert_legacy_blend_mode(ntree, ma->blend_method, ntrees_additive); + } + ma->blend_method = MA_BM_BLEND; + } + else if (ma->blend_method == 2 /* MA_BM_MULTIPLY */) { + if (ma->use_nodes) { + do_versions_material_convert_legacy_blend_mode(ntree, ma->blend_method, ntrees_multiply); + } + ma->blend_method = MA_BM_BLEND; + } + else { + /* Still tag the group nodes as not using legacy blend modes. */ + if (ma->use_nodes) { + do_versions_material_convert_legacy_blend_mode(ntree, -1, ntrees_nolegacy); + } + } + } + /* Remove group nodetree that are used by material using non-legacy blend mode. */ + GHashIterState iter = {0}; + bNodeTree *ntree; + bool error = false; + while (BLI_gset_pop(ntrees_nolegacy, (GSetIterState *)&iter, (void **)&ntree)) { + if (BLI_gset_remove(ntrees_additive, ntree, NULL)) { + error = true; + } + if (BLI_gset_remove(ntrees_multiply, ntree, NULL)) { + error = true; + } + } + BLI_gset_free(ntrees_nolegacy, NULL); + /* Convert remaining group nodetree. */ + GHashIterState iter_add = {0}; + GHashIterState iter_mul = {0}; + while (BLI_gset_pop(ntrees_additive, (GSetIterState *)&iter_add, (void **)&ntree)) { + do_versions_material_convert_legacy_blend_mode(ntree, 1 /* MA_BM_ADD */, NULL); + } + while (BLI_gset_pop(ntrees_multiply, (GSetIterState *)&iter_mul, (void **)&ntree)) { + do_versions_material_convert_legacy_blend_mode(ntree, 2 /* MA_BM_MULTIPLY */, NULL); + } + BLI_gset_free(ntrees_additive, NULL); + BLI_gset_free(ntrees_multiply, NULL); + + if (error) { + BKE_report(reports, RPT_ERROR, "Eevee material conversion problem. Error in console"); + printf( + "One or more group nodetrees containing a material output were found" + " in both a material using deprecated blend mode and a normal one.\n" + "Nothing in these nodetrees was changed and manual update is required.\n"); + } + } } /* NOTE: This version patch is intended for versions < 2.52.2, diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index ccc2d6ba020..738745f3072 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -1474,21 +1474,10 @@ static void material_transparent(Material *ma, DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_CUSTOM); - DRWState cur_state = DRW_STATE_WRITE_COLOR; + DRWState cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM; cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL; cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; - switch (ma->blend_method) { - case MA_BM_ADD: - case MA_BM_MULTIPLY: - case MA_BM_BLEND: - cur_state |= DRW_STATE_BLEND_CUSTOM; - break; - default: - BLI_assert(0); - break; - } - /* Disable other blend modes and use the one we want. */ DRW_shgroup_state_disable(*shgrp, all_state); DRW_shgroup_state_enable(*shgrp, cur_state); @@ -1564,8 +1553,6 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, &shgrp_depth_array[i], &shgrp_depth_clip_array[i]); break; - case MA_BM_ADD: - case MA_BM_MULTIPLY: case MA_BM_BLEND: material_transparent(ma_array[i], sldata, diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 152ecb85991..1d1ccef8846 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -306,12 +306,12 @@ typedef struct Material { /* blend_method */ enum { - MA_BM_SOLID, - MA_BM_ADD, - MA_BM_MULTIPLY, - MA_BM_CLIP, - MA_BM_HASHED, - MA_BM_BLEND, + MA_BM_SOLID = 0, + // MA_BM_ADD = 1, /* deprecated */ + // MA_BM_MULTIPLY = 2, /* deprecated */ + MA_BM_CLIP = 3, + MA_BM_HASHED = 4, + MA_BM_BLEND = 5, }; /* blend_flag */ diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 6378ee15279..8bfc4bf6313 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -719,16 +719,6 @@ void RNA_def_material(BlenderRNA *brna) static EnumPropertyItem prop_eevee_blend_items[] = { {MA_BM_SOLID, "OPAQUE", 0, "Opaque", "Render surface without transparency"}, - {MA_BM_ADD, - "ADD", - 0, - "Additive", - "Render surface and blend the result with additive blending"}, - {MA_BM_MULTIPLY, - "MULTIPLY", - 0, - "Multiply", - "Render surface and blend the result with multiplicative blending"}, {MA_BM_CLIP, "CLIP", 0, |