Current situation

A mesh can consist out of multiple material. Take a character with clothing's. the skin can be a different material as the different clothing's. During compositing it is a common use-case to only do a part of the composit on only a specific material. Currently this can not be done.

In blender movies this feature is known to be implemented, but until now it never got integrated into trunk.
Proposal

With material index the Blender internal renderer will be capable of creating a buffer containing the material indexes of the first pixel-hit. This will be implemented in the same manner as the object index.

In the compositor the ID Mask node can be used to extract the information out of the Render pass.
Impact
User interface

On the properties-space the next changes will be done

    Scene⇒Render layer⇒Passes⇒Material index will be added
    Material⇒Options⇒Pass index will be added

DNA

    Material struct will get an new field called “index”. this will be a short-type.
    Material struct the field pad will be removed.
    A new Render-layer pass will be added (bit 1«18)

RNA

    Material RNA is updated (based on “pass index” from object)
    Render layer RNA is updated (based on IndexOB)

Blender internal renderer

The Blender internal renderer will process the render pass as a copy of the Object index.
Blender compositor

The render layer input will get a new output socket called “IndexMA”
Usage

An example on how to use material index can be found at:

https://svn.blender.org/svnroot/bf-blender/trunk/lib/tests/compositing/composite_materialindex.blend

This is also example of a commit message longer than the commit itself :)
This commit is contained in:
2011-07-04 18:14:41 +00:00
parent 7c15143449
commit c4491f558b
15 changed files with 70 additions and 19 deletions

View File

@@ -729,6 +729,7 @@ class MATERIAL_PT_options(MaterialButtonsPanel, bpy.types.Panel):
col.prop(mat, "use_vertex_color_paint")
col.prop(mat, "use_vertex_color_light")
col.prop(mat, "use_object_color")
col.prop(mat, "pass_index")
class MATERIAL_PT_shadow(MaterialButtonsPanel, bpy.types.Panel):

View File

@@ -141,6 +141,7 @@ class RENDER_PT_layers(RenderButtonsPanel, bpy.types.Panel):
col.prop(rl, "use_pass_uv")
col.prop(rl, "use_pass_mist")
col.prop(rl, "use_pass_object_index")
col.prop(rl, "use_pass_material_index")
col.prop(rl, "use_pass_color")
col = split.column()

View File

@@ -319,9 +319,10 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat);
#define RRES_OUT_REFRACT 12
#define RRES_OUT_INDIRECT 13
#define RRES_OUT_INDEXOB 14
#define RRES_OUT_MIST 15
#define RRES_OUT_EMIT 16
#define RRES_OUT_ENV 17
#define RRES_OUT_INDEXMA 15
#define RRES_OUT_MIST 16
#define RRES_OUT_EMIT 17
#define RRES_OUT_ENV 18
/* note: types are needed to restore callbacks, don't change values */
#define CMP_NODE_VIEWER 201

View File

@@ -3156,7 +3156,9 @@ static void force_hidden_passes(bNode *node, int passflag)
if(!(passflag & SCE_PASS_INDIRECT)) sock->flag |= SOCK_UNAVAIL;
sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB);
if(!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL;
sock= BLI_findlink(&node->outputs, RRES_OUT_MIST);
sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXMA);
if(!(passflag & SCE_PASS_INDEXMA)) sock->flag |= SOCK_UNAVAIL;
sock= BLI_findlink(&node->outputs, RRES_OUT_MIST);
if(!(passflag & SCE_PASS_MIST)) sock->flag |= SOCK_UNAVAIL;
sock= BLI_findlink(&node->outputs, RRES_OUT_EMIT);
if(!(passflag & SCE_PASS_EMIT)) sock->flag |= SOCK_UNAVAIL;

View File

@@ -480,7 +480,11 @@ static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, Sc
te->name= "Index Object";
te->directdata= &srl->passflag;
te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_RGBA));
te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDEXMA));
te->name= "Index Material";
te->directdata= &srl->passflag;
te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_RGBA));
te->name= "Color";
te->directdata= &srl->passflag;

View File

@@ -161,7 +161,7 @@ typedef struct Material {
int mapto_textured; /* render-time cache to optimise texture lookups */
short shadowonly_flag; /* "shadowsonly" type */
short pad;
short index; /* custom index for render passes */
ListBase gpumaterial; /* runtime */
} Material;

View File

@@ -201,6 +201,7 @@ typedef struct SceneRenderLayer {
#define SCE_PASS_RAYHITS (1<<15)
#define SCE_PASS_EMIT (1<<16)
#define SCE_PASS_ENVIRONMENT (1<<17)
#define SCE_PASS_INDEXMA (1<<18)
/* note, srl->passflag is treestore element 'nr' in outliner, short still... */

View File

@@ -1676,6 +1676,11 @@ void RNA_def_material(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Light Group", "Limit lighting to lamps in this Group");
RNA_def_property_update(prop, 0, "rna_Material_update");
prop= RNA_def_property(srna, "pass_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "index");
RNA_def_property_ui_text(prop, "Pass Index", "Index # for the IndexMA render pass");
RNA_def_property_update(prop, NC_OBJECT, NULL);
/* flags */
prop= RNA_def_property(srna, "use_light_group_exclusive", PROP_BOOLEAN, PROP_NONE);

View File

@@ -388,7 +388,8 @@ static void rna_def_render_pass(BlenderRNA *brna)
{SCE_PASS_MIST, "MIST", 0, "Mist", ""},
{SCE_PASS_EMIT, "EMIT", 0, "Emit", ""},
{SCE_PASS_ENVIRONMENT, "ENVIRONMENT", 0, "Environment", ""},
{0, NULL, 0, NULL, NULL}};
{SCE_PASS_INDEXMA, "MATERIAL_INDEX", 0, "Material Index", ""},
{0, NULL, 0, NULL, NULL}};
srna= RNA_def_struct(brna, "RenderPass", NULL);
RNA_def_struct_ui_text(srna, "Render Pass", "");

View File

@@ -1515,7 +1515,13 @@ void rna_def_render_layer_common(StructRNA *srna, int scene)
if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop= RNA_def_property(srna, "use_pass_color", PROP_BOOLEAN, PROP_NONE);
prop= RNA_def_property(srna, "use_pass_material_index", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_INDEXMA);
RNA_def_property_ui_text(prop, "Material Index", "Deliver material index pass");
if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop= RNA_def_property(srna, "use_pass_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_RGBA);
RNA_def_property_ui_text(prop, "Color", "Deliver shade-less color pass");
if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");

View File

@@ -53,7 +53,8 @@ static bNodeSocketType cmp_node_rlayers_out[]= {
{ SOCK_RGBA, 0, "Refract", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, "Indirect", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 0, "IndexOB", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 0, "Mist", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 0, "IndexMA", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 0, "Mist", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, "Emit", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_RGBA, 0, "Environment",0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
@@ -211,7 +212,9 @@ static void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack *
out[RRES_OUT_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDIRECT);
if(out[RRES_OUT_INDEXOB]->hasoutput)
out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB);
if(out[RRES_OUT_MIST]->hasoutput)
if(out[RRES_OUT_INDEXMA]->hasoutput)
out[RRES_OUT_INDEXMA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXMA);
if(out[RRES_OUT_MIST]->hasoutput)
out[RRES_OUT_MIST]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_MIST);
if(out[RRES_OUT_EMIT]->hasoutput)
out[RRES_OUT_EMIT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_EMIT);
@@ -326,7 +329,7 @@ static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, in
CompBuf *buf;
int buftype= CB_VEC3;
if(ELEM3(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST))
if(ELEM4(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST, SCE_PASS_INDEXMA))
buftype= CB_VAL;
else if(passcode==SCE_PASS_VECTOR)
buftype= CB_VEC4;
@@ -373,6 +376,8 @@ static void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStac
out[RRES_OUT_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDIRECT);
if(out[RRES_OUT_INDEXOB]->hasoutput)
out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
if(out[RRES_OUT_INDEXMA]->hasoutput)
out[RRES_OUT_INDEXMA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXMA);
if(out[RRES_OUT_MIST]->hasoutput)
out[RRES_OUT_MIST]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_MIST);
if(out[RRES_OUT_EMIT]->hasoutput)

View File

@@ -383,7 +383,11 @@ static const char *get_pass_name(int passtype, int channel)
if(channel==-1) return "IndexOB";
return "IndexOB.X";
}
if(passtype == SCE_PASS_MIST) {
if(passtype == SCE_PASS_INDEXMA) {
if(channel==-1) return "IndexMA";
return "IndexMA.X";
}
if(passtype == SCE_PASS_MIST) {
if(channel==-1) return "Mist";
return "Mist.Z";
}
@@ -448,6 +452,9 @@ static int passtype_from_name(char *str)
if(strcmp(str, "IndexOB")==0)
return SCE_PASS_INDEXOB;
if(strcmp(str, "IndexMA")==0)
return SCE_PASS_INDEXMA;
if(strcmp(str, "Mist")==0)
return SCE_PASS_MIST;
@@ -631,7 +638,9 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int
render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT);
if(srl->passflag & SCE_PASS_INDEXOB)
render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB);
if(srl->passflag & SCE_PASS_MIST)
if(srl->passflag & SCE_PASS_INDEXMA)
render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA);
if(srl->passflag & SCE_PASS_MIST)
render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST);
if(rl->passflag & SCE_PASS_RAYHITS)
render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS);

View File

@@ -515,7 +515,15 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
*fp= (float)shi->obr->ob->index;
}
break;
case SCE_PASS_MIST:
case SCE_PASS_INDEXMA:
/* no filter */
if(shi->vlr) {
fp= rpass->rect + offset;
if(*fp==0.0f)
*fp= (float)shi->mat->index;
}
break;
case SCE_PASS_MIST:
/* */
col= &shr->mist;
pixsize= 1;

View File

@@ -1455,7 +1455,7 @@ int shade_samples(ShadeSample *ssamp, PixStr *ps, int x, int y)
shade_samples_do_AO(ssamp);
/* if shade (all shadepinputs have same passflag) */
if(ssamp->shi[0].passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB)) {
if(ssamp->shi[0].passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB|SCE_PASS_INDEXMA)) {
for(samp=0; samp<ssamp->tot; samp++, shi++, shr++) {
shade_input_set_shade_texco(shi);

View File

@@ -3497,7 +3497,7 @@ static void add_transp_obindex(RenderLayer *rl, int offset, Object *ob)
RenderPass *rpass;
for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
if(rpass->passtype == SCE_PASS_INDEXOB) {
if(rpass->passtype == SCE_PASS_INDEXOB||rpass->passtype == SCE_PASS_INDEXMA) {
float *fp= rpass->rect + offset;
*fp= (float)ob->index;
break;
@@ -3820,7 +3820,7 @@ static int shade_tra_samples(ShadeSample *ssamp, StrandShadeCache *cache, int x,
shade_samples_do_AO(ssamp);
/* if shade (all shadepinputs have same passflag) */
if(shi->passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB)) {
if(shi->passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB|SCE_PASS_INDEXMA)) {
for(samp=0; samp<ssamp->tot; samp++, shi++, shr++) {
shade_input_set_shade_texco(shi);
shade_input_do_shade(shi, shr);
@@ -4115,6 +4115,13 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
add_transp_obindex(rlpp[a], od, obr->ob);
}
}
if(addpassflag & SCE_PASS_INDEXMA) {
ObjectRen *obr= R.objectinstance[zrow[totface-1].obi].obr;
if(obr->ob) {
for(a= 0; a<totfullsample; a++)
add_transp_obindex(rlpp[a], od, obr->ob);
}
}
/* for each mask-sample we alpha-under colors. then in end it's added using filter */
memset(samp_shr, 0, sizeof(ShadeResult)*osa);