Bugfix & Feature fix: Only Shadow Material options

Patch from Miika Hämäläinen.

The old Material "Only Shadow" used an ancient 'best guess'
formula using Lamp Distance and some averaging for converting
shadow values to alpha.
A couple of bug reporters already complained about the not
very predictable renders. Miika fixed this by adding two
new options, to only give the true shadow factor exclusively,
or to give a result including light intensity values.

More info:
http://projects.blender.org/tracker/index.php?func=detail&aid=26413&group_id=9&atid=127
This commit is contained in:
Ton Roosendaal 2011-03-08 16:08:43 +00:00
parent 3d05311d3c
commit 3a43e08deb
4 changed files with 96 additions and 19 deletions

View File

@ -752,10 +752,13 @@ class MATERIAL_PT_shadow(MaterialButtonsPanel, bpy.types.Panel):
col = split.column()
col.prop(mat, "use_shadows", text="Receive")
col.prop(mat, "use_transparent_shadows", text="Receive Transparent")
col.prop(mat, "use_only_shadow", text="Shadows Only")
if simple_material(base_mat):
col.prop(mat, "use_cast_shadows_only", text="Cast Only")
col.prop(mat, "shadow_cast_alpha", text="Casting Alpha")
col.prop(mat, "use_only_shadow", text="ShadowsOnly")
sub = col.column()
sub.active = mat.use_only_shadow
sub.prop(mat, "shadow_only_type", text="")
col = split.column()
if simple_material(base_mat):
@ -771,6 +774,7 @@ class MATERIAL_PT_shadow(MaterialButtonsPanel, bpy.types.Panel):
col.prop(mat, "use_cast_approximate")
class MATERIAL_PT_transp_game(MaterialButtonsPanel, bpy.types.Panel):
bl_label = "Transparency"
bl_options = {'DEFAULT_CLOSED'}

View File

@ -160,7 +160,8 @@ typedef struct Material {
short sss_flag, sss_preset;
int mapto_textured; /* render-time cache to optimise texture lookups */
int pad4;
short shadowonly_flag; /* "shadowsonly" type */
short pad;
ListBase gpumaterial; /* runtime */
} Material;
@ -238,6 +239,11 @@ typedef struct Material {
#define MA_RAYMIR_FADETOSKY 0
#define MA_RAYMIR_FADETOMAT 1
/* shadowonly_flag */
#define MA_SO_OLD 0
#define MA_SO_SHADOW 1
#define MA_SO_SHADED 2
/* shade_flag */
#define MA_CUBIC 1
#define MA_OBCOLOR 2

View File

@ -1583,6 +1583,12 @@ void RNA_def_material(BlenderRNA *brna)
{MA_SPHERE_A, "SPHERE_A", ICON_MAT_SPHERE_SKY, "Flat", "Preview type: Large sphere with sky"},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem prop_shadows_only_items[] = {
{MA_SO_OLD, "SO_OLD", 0, "Shadow and Distance", ""},
{MA_SO_SHADOW, "SO_SHADOW", 0, "Shadow Only", ""},
{MA_SO_SHADED, "SO_SHADED", 0, "Shadow and Shading", ""},
{0, NULL, 0, NULL, NULL}};
srna= RNA_def_struct(brna, "Material", "ID");
RNA_def_struct_ui_text(srna, "Material", "Material datablock to defined the appearance of geometric objects for rendering");
RNA_def_struct_ui_icon(srna, ICON_MATERIAL_DATA);
@ -1713,6 +1719,12 @@ void RNA_def_material(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "mode", MA_ONLYSHADOW);
RNA_def_property_ui_text(prop, "Only Shadow", "Renders shadows as the material's alpha value, making materials transparent except for shadowed areas");
RNA_def_property_update(prop, 0, "rna_Material_update");
prop= RNA_def_property(srna, "shadow_only_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "shadowonly_flag");
RNA_def_property_enum_items(prop, prop_shadows_only_items);
RNA_def_property_ui_text(prop, "Shadow Type", "How to draw shadows");
RNA_def_property_update(prop, 0, "rna_Material_update");
prop= RNA_def_property(srna, "use_face_texture", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", MA_FACETEXTURE);

View File

@ -1502,10 +1502,10 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr)
float inpr, lv[3];
float *view, shadfac[4];
float ir, accum, visifac, lampdist;
float shaded = 0.0f, lightness = 0.0f;
view= shi->view;
accum= ir= 0.0f;
lights= get_lights(shi);
@ -1522,27 +1522,69 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr)
if(lar->shb || (lar->mode & LA_SHAD_RAY)) {
visifac= lamp_get_visibility(lar, shi->co, lv, &lampdist);
if(visifac <= 0.0f) {
ir+= 1.0f;
accum+= 1.0f;
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
ir+= 1.0f;
accum+= 1.0f;
}
continue;
}
inpr= INPR(shi->vn, lv);
if(inpr <= 0.0f) {
ir+= 1.0f;
accum+= 1.0f;
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
ir+= 1.0f;
accum+= 1.0f;
}
continue;
}
}
lamp_get_shadow(lar, shi, inpr, shadfac, shi->depth);
ir+= 1.0f;
accum+= (1.0f-visifac) + (visifac)*rgb_to_grayscale(shadfac)*shadfac[3];
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
/* Old "Shadows Only" */
ir+= 1.0f;
accum+= (1.0f-visifac) + (visifac)*rgb_to_grayscale(shadfac)*shadfac[3];
}
else {
ir+= lar->energy;
shaded += rgb_to_grayscale(shadfac)*shadfac[3] * visifac * lar->energy;
if (shi->mat->shadowonly_flag == MA_SO_SHADOW) {
lightness += visifac * lar->energy;
}
}
}
}
/* Apply shadows as alpha */
if(ir>0.0f) {
accum/= ir;
shr->alpha= (shi->mat->alpha)*(1.0f-accum);
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
accum = 1.0f - accum/ir;
}
else {
shaded/= ir;
lightness/= ir;
if (shi->mat->shadowonly_flag == MA_SO_SHADOW) {
if (lightness > 0.0f) {
/* Get shadow value from between 0.0f and non-shadowed lightness */
accum = (lightness - shaded) / (lightness);
}
else {
accum = 0.0f;
}
}
else { /* shadowonly_flag == MA_SO_SHADED */
/* Use shaded value */
accum = 1.0f - shaded;
}}
shr->alpha= (shi->mat->alpha)*(accum);
}
else {
/* If "fully shaded", use full alpha even on areas that have no lights */
if (shi->mat->shadowonly_flag == MA_SO_SHADED) shr->alpha=1.0f;
else shr->alpha= 0.f;
}
else shr->alpha= 0.f;
}
/* quite disputable this... also note it doesn't mirror-raytrace */
@ -1551,18 +1593,31 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr)
if(R.wrld.mode & WO_AMB_OCC) {
f= R.wrld.aoenergy*shi->amb;
if(R.wrld.aomix==WO_AOADD) {
f= f*(1.0f - rgb_to_grayscale(shi->ao));
shr->alpha= (shr->alpha + f)*f;
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
f= f*(1.0f - rgb_to_grayscale(shi->ao));
shr->alpha= (shr->alpha + f)*f;
}
else {
shr->alpha -= f*rgb_to_grayscale(shi->ao);
if (shr->alpha<0.0f) shr->alpha=0.0f;
}
}
else
else /* AO Multiply */
shr->alpha= (1.0f - f)*shr->alpha + f*(1.0f - (1.0f - shr->alpha)*rgb_to_grayscale(shi->ao));
}
if(R.wrld.mode & WO_ENV_LIGHT) {
f= R.wrld.ao_env_energy*shi->amb*(1.0f - rgb_to_grayscale(shi->env));
shr->alpha= (shr->alpha + f)*f;
if (shi->mat->shadowonly_flag == MA_SO_OLD) {
f= R.wrld.ao_env_energy*shi->amb*(1.0f - rgb_to_grayscale(shi->env));
shr->alpha= (shr->alpha + f)*f;
}
else {
f= R.wrld.ao_env_energy*shi->amb;
shr->alpha -= f*rgb_to_grayscale(shi->env);
if (shr->alpha<0.0f) shr->alpha=0.0f;
}
}
}
}