Added a roughness parameter for refractions (for scattering of the rays

within an object)

With this, one can create a translucent material with a smooth surface and
with a milky look.

The final refraction roughness has to be calculated using the surface
roughness and the refraction roughness because those two are correlated
for refractions. If a ray hits a rough surface of a translucent material,
it is scattered while entering the surface. Then it is scattered further
within the object. The calculation I'm using is the following:

RefrRoughnessFinal = 1.0 - (1.0 - Roughness) * (1.0 - RefrRoughness)
This commit is contained in:
2016-07-20 11:13:00 +02:00
parent 50ea5e3e34
commit dbad91ca6d
5 changed files with 93 additions and 28 deletions

View File

@@ -31,6 +31,7 @@ shader node_disney_bsdf(
float ClearcoatGloss = 1.0,
float IOR = 1.45,
float Transparency = 0.0,
float RefractionRoughness = 0.0,
normal Normal = N,
normal ClearcoatNormal = N,
normal Tangent = normalize(dPdu),
@@ -39,23 +40,27 @@ shader node_disney_bsdf(
{
float f = max(IOR, 1e-5);
float eta = backfacing() ? 1.0 / f : f;
float cosi = dot(I, Normal);
float Fr = fresnel_dielectric_cos(cosi, eta);
float trans = clamp(Transparency, 0.0, 1.0);
float metal = clamp(Metallic, 0.0, 1.0);
float specWeight = mix(1.0, Fr, mix(trans, 0.0, metal));
float cosNO = dot(Normal, I);
float Fr = fresnel_dielectric_cos(cosNO, eta);
float diffuse_weight = (1.0 - clamp(Metallic, 0.0, 1.0)) * (1.0 - clamp(Transparency, 0.0, 1.0));
float transp = clamp(Transparency, 0.0, 1.0) * (1.0 - clamp(Metallic, 0.0, 1.0));
float specular_weight = (1.0 - transp);
if (metal < 1.0) {
float refr_roughness = 1.0 - (1.0 - Roughness) * (1.0 - RefractionRoughness);
if (diffuse_weight > 0.0) {
BSDF = (((Subsurface * BaseColor * bssrdf_burley(Normal, vector(1.0, 1.0, 1.0), 0.0, BaseColor)) + disney_diffuse(Normal, BaseColor, Roughness) * (1.0 - Subsurface))
+ disney_sheen(Normal, BaseColor, Sheen, SheenTint)) * (1.0 - metal) * (1.0 - trans);
+ disney_sheen(Normal, BaseColor, Sheen, SheenTint)) * diffuse_weight;
}
if (Specular != 0.0 || Metallic != 0.0) {
BSDF = BSDF + specWeight * disney_specular(Normal, Tangent, BaseColor, Metallic, Specular,
BSDF = BSDF + specular_weight * disney_specular(Normal, Tangent, BaseColor, Metallic, Specular,
SpecularTint, Roughness, Anisotropic)
+ (1.0 - specWeight) * BaseColor * microfacet_ggx_refraction(Normal, Roughness * Roughness, eta);
} else if (trans > 0.0) {
BSDF = BSDF + trans * microfacet_ggx_refraction(Normal, Roughness * Roughness, eta);
+ (1.0 - specular_weight) * (Fr * disney_specular(Normal, Tangent, BaseColor, 0.0, 12.5,
SpecularTint, Roughness, 0.0) + (1.0 - Fr) * BaseColor * microfacet_ggx_refraction(Normal, refr_roughness * refr_roughness, eta));
} else if (transp > 0.0) {
BSDF = BSDF + transp * (disney_specular(Normal, Tangent, BaseColor, 0.0, 12.5, SpecularTint, Roughness, 0.0)
+ BaseColor * microfacet_ggx_refraction(Normal, refr_roughness * refr_roughness, eta));
}
if (Clearcoat != 0.0) {

View File

@@ -137,14 +137,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
switch(type) {
case CLOSURE_BSDF_DISNEY_ID: {
uint specular_offset, roughness_offset, specularTint_offset, anisotropic_offset,
sheen_offset, sheenTint_offset, clearcoat_offset, clearcoatGloss_offset, eta_offset, transparency_offset;
uint tmp0, tmp1;
uint specular_offset, roughness_offset, specularTint_offset, anisotropic_offset, sheen_offset,
sheenTint_offset, clearcoat_offset, clearcoatGloss_offset, eta_offset, transparency_offset, refr_roughness_offset;
uint tmp0;
uint4 data_node2 = read_node(kg, offset);
decode_node_uchar4(data_node.z, &specular_offset, &roughness_offset, &specularTint_offset, &anisotropic_offset);
decode_node_uchar4(data_node.w, &sheen_offset, &sheenTint_offset, &clearcoat_offset, &clearcoatGloss_offset);
decode_node_uchar4(data_node2.x, &eta_offset, &transparency_offset, &tmp0, &tmp1);
decode_node_uchar4(data_node2.x, &eta_offset, &transparency_offset, &refr_roughness_offset, &tmp0);
// get disney parameters
float metallic = param1;
@@ -158,6 +158,8 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float clearcoat = stack_load_float(stack, clearcoat_offset);
float clearcoatGloss = stack_load_float(stack, clearcoatGloss_offset);
float transparency = stack_load_float(stack, transparency_offset);
float refr_roughness = stack_load_float(stack, refr_roughness_offset);
refr_roughness = 1.0f - (1.0f - roughness) * (1.0f - refr_roughness);
float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
eta = (ccl_fetch(sd, flag) & SD_BACKFACING) ? 1.0f / eta : eta;
@@ -170,10 +172,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float diffuse_weight = (1.0f - clamp(metallic, 0.0f, 1.0f)) * (1.0f - clamp(transparency, 0.0f, 1.0f)); // lerp(1.0f - clamp(metallic, 0.0f, 1.0f), 0.0f, lerp(clamp(transparency, 0.0f, 1.0f), 0.0f, clamp(metallic, 0.0f, 1.0f)));
float transp = clamp(transparency, 0.0f, 1.0f) * (1.0f - clamp(metallic, 0.0f, 1.0f)); // lerp(clamp(transparency, 0.0f, 1.0f), 0.0f, clamp(metallic, 0.0f, 1.0f));
float specular_weight = 1.0f * (1.0f - transp) + fresnel * transp; // lerp(1.0f, fresnel, transp);
if (specular == 0.0f && metallic == 0.0f) {
specular_weight = 1.0f - transparency;
}
float specular_weight = (1.0f - transp); // + fresnel * transp; // lerp(1.0f, fresnel, transp);
// get the base color
uint4 data_base_color = read_node(kg, offset);
@@ -311,7 +310,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->color0 = baseColor;
sc->data0 = metallic;
sc->data1 = specular;
sc->data1 = specular; // (1.0f - transparency) * specular + transparency * specular * 12.5f/* equals division by 0.08f */;
sc->data2 = specularTint;
sc->data3 = roughness;
sc->data4 = anisotropic;
@@ -321,8 +320,66 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
}
}
/* specular refraction */
/* BSDF */
if (specular_weight < 1.0f) {
if (ccl_fetch(sd, num_closure) + 1 < MAX_CLOSURE) {
#ifdef __CAUSTICS_TRICKS__
if (!kernel_data.integrator.caustics_reflective &&
!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
{
break;
}
#endif
/* reflection */
sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
sc->weight = weight;
sc->sample_weight = sample_weight;
sc = svm_node_closure_get_bsdf(sd, mix_weight * (1.0f - specular_weight) * fresnel);
#ifdef __CAUSTICS_TRICKS__
if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
if (sc) {
sc->N = N;
sc->T = stack_load_float3(stack, data_node.y);
sc->color0 = baseColor;
sc->data0 = 0.0f;
sc->data1 = 12.5f; // == (1.0f / 0.08f)
sc->data2 = specularTint;
sc->data3 = roughness;
sc->data4 = 0.0f;
ccl_fetch(sd, flag) |= bsdf_disney_specular_setup(sc);
}
}
#ifdef __CAUSTICS_TRICKS__
if (!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
/* refraction */
sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
sc->weight = weight * baseColor;
sc->sample_weight = sample_weight;
sc = svm_node_closure_get_bsdf(sd, mix_weight * (1.0f - specular_weight) * (1.0f - fresnel));
if (sc) {
sc->N = N;
sc->data0 = refr_roughness * refr_roughness;
sc->data1 = refr_roughness * refr_roughness;
sc->data2 = eta;
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(sc);
}
}
}
/* specular refraction */
/*if (specular_weight < 1.0f) {
if (ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
sc->weight = weight * baseColor;
@@ -333,14 +390,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if (sc) {
sc->N = N;
sc->data0 = roughness * roughness;
sc->data1 = roughness * roughness;
sc->data0 = refr_roughness * refr_roughness;
sc->data1 = refr_roughness * refr_roughness;
sc->data2 = eta;
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(sc);
}
}
}
}*/
/* clearcoat */
if (clearcoat > 0.0f) {

View File

@@ -2127,6 +2127,7 @@ DisneyBsdfNode::DisneyBsdfNode()
add_input("ClearcoatGloss", SHADER_SOCKET_FLOAT, 1.0f);
add_input("IOR", SHADER_SOCKET_FLOAT, 1.45f);
add_input("Transparency", SHADER_SOCKET_FLOAT, 0.0f);
add_input("RefractionRoughness", SHADER_SOCKET_FLOAT, 0.0f);
add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
add_input("ClearcoatNormal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
add_input("Tangent", SHADER_SOCKET_VECTOR, ShaderInput::TANGENT);
@@ -2138,7 +2139,7 @@ DisneyBsdfNode::DisneyBsdfNode()
void DisneyBsdfNode::compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface,
ShaderInput *specular, ShaderInput *roughness, ShaderInput *specularTint, ShaderInput *anisotropic,
ShaderInput *sheen, ShaderInput *sheenTint, ShaderInput *clearcoat, ShaderInput *clearcoatGloss,
ShaderInput *ior, ShaderInput *transparency)
ShaderInput *ior, ShaderInput *transparency, ShaderInput *refr_roughness)
{
ShaderInput *base_color_in = input("BaseColor");
ShaderInput *normal_in = input("Normal");
@@ -2166,6 +2167,7 @@ void DisneyBsdfNode::compile(SVMCompiler& compiler, ShaderInput *metallic, Shade
int clearcoatGloss_offset = compiler.stack_assign(clearcoatGloss);
int ior_offset = compiler.stack_assign(ior);
int transparency_offset = compiler.stack_assign(transparency);
int refr_roughness_offset = compiler.stack_assign(refr_roughness);
compiler.add_node(NODE_CLOSURE_BSDF,
compiler.encode_uchar4(closure,
@@ -2179,7 +2181,7 @@ void DisneyBsdfNode::compile(SVMCompiler& compiler, ShaderInput *metallic, Shade
compiler.encode_uchar4(specular_offset, roughness_offset, specularTint_offset, anisotropic_offset),
compiler.encode_uchar4(sheen_offset, sheenTint_offset, clearcoat_offset, clearcoatGloss_offset));
compiler.add_node(compiler.encode_uchar4(ior_offset, transparency_offset, SVM_STACK_INVALID, SVM_STACK_INVALID),
compiler.add_node(compiler.encode_uchar4(ior_offset, transparency_offset, refr_roughness_offset, SVM_STACK_INVALID),
SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID);
compiler.add_node(((base_color_in->link) ? compiler.stack_assign(base_color_in) : SVM_STACK_INVALID),
@@ -2192,7 +2194,7 @@ void DisneyBsdfNode::compile(SVMCompiler& compiler)
{
compile(compiler, input("Metallic"), input("Subsurface"), input("Specular"), input("Roughness"),
input("SpecularTint"), input("Anisotropic"), input("Sheen"), input("SheenTint"),
input("Clearcoat"), input("ClearcoatGloss"), input("IOR"), input("Transparency"));
input("Clearcoat"), input("ClearcoatGloss"), input("IOR"), input("Transparency"), input("RefractionRoughness"));
}
void DisneyBsdfNode::compile(OSLCompiler& compiler)

View File

@@ -423,7 +423,7 @@ public:
void compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface,
ShaderInput *specular, ShaderInput *roughness, ShaderInput *specularTint, ShaderInput *anisotropic,
ShaderInput *sheen, ShaderInput *sheenTint, ShaderInput *clearcoat, ShaderInput *clearcoatGloss,
ShaderInput *ior, ShaderInput *transparency);
ShaderInput *ior, ShaderInput *transparency, ShaderInput *refr_roughness);
ClosureType closure;

View File

@@ -43,6 +43,7 @@ static bNodeSocketTemplate sh_node_bsdf_disney_in[] = {
{ SOCK_FLOAT, 1, N_("ClearcoatGloss"), 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_("RefractionRoughness"), 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_("ClearcoatNormal"), 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},