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.
This commit is contained in:
Clément Foucault 2019-08-13 00:11:36 +02:00
parent d5002f007e
commit 13d469e6f0
Notes: blender-bot 2023-02-14 00:13:36 +01:00
Referenced by issue #71584, Nodes changed after import in blender 2.81 (due to versioning code of blend mode refactor)
7 changed files with 198 additions and 37 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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 */

View File

@ -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,