Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2013-09-04 02:39:17 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2013-09-04 02:39:17 +0400
commitb314209356288c3768faa1d7fbd7b1bf9d179a7a (patch)
tree2fafde8bdccff99e294acb34dbca90605e2e5327 /intern
parent9467d9940583d6c3a2e1b83f854453da9e64fdd7 (diff)
Cycles: add a sharpness input to the Cubic SSS falloff. When set to 1 this will
give a result more similar to the Compatible falloff option. The scale is x2 though to keep the perceived scatter radius roughly the same while changing the sharpness. Difference with compatible will be mainly on non-flat geometry.
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/kernel/closure/bssrdf.h62
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.cpp31
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.h2
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp4
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h2
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp1
-rw-r--r--intern/cycles/kernel/shaders/node_subsurface_scattering.osl9
-rw-r--r--intern/cycles/kernel/shaders/stdosl.h7
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h15
-rw-r--r--intern/cycles/render/nodes.cpp17
-rw-r--r--intern/cycles/render/nodes.h2
11 files changed, 116 insertions, 36 deletions
diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h
index d6f889f3285..4ceff655dd5 100644
--- a/intern/cycles/kernel/closure/bssrdf.h
+++ b/intern/cycles/kernel/closure/bssrdf.h
@@ -31,6 +31,7 @@ __device int bssrdf_setup(ShaderClosure *sc, ClosureType type)
}
else {
sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* texture blur */
+ sc->T.x = clamp(sc->T.x, 0.0f, 1.0f); /* sharpness */
sc->type = type;
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF;
@@ -95,17 +96,49 @@ __device void bssrdf_gaussian_sample(ShaderClosure *sc, float xi, float *r, floa
__device float bssrdf_cubic_eval(ShaderClosure *sc, float r)
{
- const float Rm = sc->data0;
+ const float sharpness = sc->T.x;
- if(r >= Rm)
- return 0.0f;
-
- /* integrate (2*pi*r * 10*(R - r)^3)/(pi * R^5) from 0 to R = 1 */
- const float Rm5 = (Rm*Rm) * (Rm*Rm) * Rm;
- const float f = Rm - min(r, Rm);
- const float f3 = f*f*f;
+ if(sharpness == 0.0f) {
+ const float Rm = sc->data0;
+
+ if(r >= Rm)
+ return 0.0f;
+
+ /* integrate (2*pi*r * 10*(R - r)^3)/(pi * R^5) from 0 to R = 1 */
+ const float Rm5 = (Rm*Rm) * (Rm*Rm) * Rm;
+ const float f = Rm - r;
+ const float num = f*f*f;
+
+ return (10.0f * num) / (Rm5 * M_PI_F);
- return (f3 * 10.0f) / (Rm5 * M_PI_F);
+ }
+ else {
+ float Rm = sc->data0*(1.0f + sharpness);
+
+ if(r >= Rm)
+ return 0.0f;
+
+ /* custom variation with extra sharpness, to match the previous code */
+ const float y = 1.0f/(1.0f + sharpness);
+ float Rmy, ry, ryinv;
+
+ if(sharpness == 1.0f) {
+ Rmy = sqrtf(Rm);
+ ry = sqrtf(r);
+ ryinv = (ry > 0.0f)? 1.0f/ry: 0.0f;
+ }
+ else {
+ Rmy = powf(Rm, y);
+ ry = powf(r, y);
+ ryinv = (r > 0.0f)? powf(r, 2.0f*y - 2.0f): 0.0f;
+ }
+
+ const float Rmy5 = (Rmy*Rmy) * (Rmy*Rmy) * Rmy;
+ const float f = Rmy - ry;
+ const float num = f*(f*f)*(y*ryinv);
+
+ return (10.0f * num) / (Rmy5 * M_PI_F);
+ }
}
__device float bssrdf_cubic_pdf(ShaderClosure *sc, float r)
@@ -143,9 +176,16 @@ __device float bssrdf_cubic_quintic_root_find(float xi)
__device void bssrdf_cubic_sample(ShaderClosure *sc, float xi, float *r, float *h)
{
- const float Rm = sc->data0;
- const float r_ = bssrdf_cubic_quintic_root_find(xi) * Rm;
+ float Rm = sc->data0;
+ float r_ = bssrdf_cubic_quintic_root_find(xi);
+ const float sharpness = sc->T.x;
+ if(sharpness != 0.0f) {
+ r_ = powf(r_, 1.0f + sharpness);
+ Rm *= (1.0f + sharpness);
+ }
+
+ r_ *= Rm;
*r = r_;
/* h^2 + r^2 = Rm^2 */
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp
index 7405b0be567..975967c0bbb 100644
--- a/intern/cycles/kernel/osl/osl_bssrdf.cpp
+++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp
@@ -56,10 +56,8 @@ public:
void setup()
{
- sc.type = CLOSURE_BSSRDF_COMPATIBLE_ID;
- sc.prim = NULL;
+ sc.type = CLOSURE_BSSRDF_CUBIC_ID;
sc.data0 = fabsf(average(radius));
- sc.data1 = 0.0f; // XXX texture blur
}
bool mergeable(const ClosurePrimitive *other) const
@@ -85,6 +83,19 @@ ClosureParam *closure_bssrdf_cubic_params()
return params;
}
+ClosureParam *closure_bssrdf_cubic_extended_params()
+{
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, sc.N),
+ CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, radius),
+ CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, sc.data1),
+ CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, sc.T.x),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(CubicBSSRDFClosure)
+ };
+ return params;
+}
+
CLOSURE_PREPARE(closure_bssrdf_cubic_prepare, CubicBSSRDFClosure)
/* Gaussian */
@@ -97,9 +108,7 @@ public:
void setup()
{
sc.type = CLOSURE_BSSRDF_GAUSSIAN_ID;
- sc.prim = NULL;
sc.data0 = fabsf(average(radius));
- sc.data1 = 0.0f; // XXX texture blurring!
}
bool mergeable(const ClosurePrimitive *other) const
@@ -125,6 +134,18 @@ ClosureParam *closure_bssrdf_gaussian_params()
return params;
}
+ClosureParam *closure_bssrdf_gaussian_extended_params()
+{
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, sc.N),
+ CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, radius),
+ CLOSURE_FLOAT_PARAM(GaussianBSSRDFClosure, sc.data1),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(GaussianBSSRDFClosure)
+ };
+ return params;
+}
+
CLOSURE_PREPARE(closure_bssrdf_gaussian_prepare, GaussianBSSRDFClosure)
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.h b/intern/cycles/kernel/osl/osl_bssrdf.h
index ee9fc7c4ac5..fc1a4c587cc 100644
--- a/intern/cycles/kernel/osl/osl_bssrdf.h
+++ b/intern/cycles/kernel/osl/osl_bssrdf.h
@@ -48,7 +48,7 @@ public:
ShaderClosure sc;
float3 radius;
- CBSSRDFClosure() : OSL::ClosurePrimitive(BSSRDF) { }
+ CBSSRDFClosure() : OSL::ClosurePrimitive(BSSRDF) { memset(&sc, 0, sizeof(sc)); }
~CBSSRDFClosure() { }
int scattering() const { return LABEL_DIFFUSE; }
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index c03e50d4313..6a3f27fb7b1 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -221,6 +221,10 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
closure_bssrdf_cubic_params(), closure_bssrdf_cubic_prepare);
register_closure(ss, "bssrdf_gaussian", id++,
closure_bssrdf_gaussian_params(), closure_bssrdf_gaussian_prepare);
+ register_closure(ss, "bssrdf_cubic", id++,
+ closure_bssrdf_cubic_extended_params(), closure_bssrdf_cubic_prepare);
+ register_closure(ss, "bssrdf_gaussian", id++,
+ closure_bssrdf_gaussian_extended_params(), closure_bssrdf_gaussian_prepare);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index e3a7e890597..6632c2c57e5 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -52,6 +52,8 @@ OSL::ClosureParam *closure_westin_backscatter_params();
OSL::ClosureParam *closure_westin_sheen_params();
OSL::ClosureParam *closure_bssrdf_cubic_params();
OSL::ClosureParam *closure_bssrdf_gaussian_params();
+OSL::ClosureParam *closure_bssrdf_cubic_extended_params();
+OSL::ClosureParam *closure_bssrdf_gaussian_extended_params();
void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
void closure_background_prepare(OSL::RendererServices *, int id, void *data);
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index c55f36bcc9d..d2ccb7da84c 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -239,6 +239,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
sc.type = bssrdf->sc.type;
sc.N = bssrdf->sc.N;
sc.data1 = bssrdf->sc.data1;
+ sc.T.x = bssrdf->sc.T.x;
sc.prim = NULL;
/* disable in case of diffuse ancestor, can't see it well then and
diff --git a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
index 18864118172..5c1d1be0ee7 100644
--- a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
+++ b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
@@ -20,14 +20,15 @@ shader node_subsurface_scattering(
color Color = 0.8,
float Scale = 1.0,
vector Radius = vector(0.1, 0.1, 0.1),
- float TextureBlur = 0.0, // XXX use
+ float TextureBlur = 0.0,
+ float Sharpness = 0.0,
string Falloff = "Cubic",
normal Normal = N,
output closure color BSSRDF = 0)
{
if(Falloff == "Gaussian")
- BSSRDF = Color * bssrdf_gaussian(N, Scale * Radius);
- else /* Cubic, hardcoded to compatible closure for now */
- BSSRDF = Color * bssrdf_cubic(N, Scale * Radius);
+ BSSRDF = Color * bssrdf_gaussian(N, Scale * Radius, TextureBlur);
+ else
+ BSSRDF = Color * bssrdf_cubic(N, Scale * Radius, TextureBlur, Sharpness);
}
diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index 7d1c2443ee7..3ad2bbc0588 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -465,11 +465,12 @@ closure color holdout() BUILTIN;
closure color ambient_occlusion() BUILTIN;
// BSSRDF
-closure color bssrdf_cubic(normal N, vector radius) BUILTIN;
-closure color bssrdf_gaussian(normal N, vector radius) BUILTIN;
+closure color bssrdf_cubic(normal N, vector radius, float texture_blur, float sharpness) BUILTIN;
+closure color bssrdf_gaussian(normal N, vector radius, float texture_blur) BUILTIN;
// Backwards compatibility
-
+closure color bssrdf_cubic(normal N, vector radius) BUILTIN;
+closure color bssrdf_gaussian(normal N, vector radius) BUILTIN;
closure color specular_toon(normal N, float size, float smooth) BUILTIN;
// Renderer state
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 42d98092b41..9a9aefa5b29 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -108,13 +108,13 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
if(mix_weight == 0.0f)
return;
- float3 N = stack_valid(data_node.y)? stack_load_float3(stack, data_node.y): sd->N;
+ float3 N = stack_valid(data_node.x)? stack_load_float3(stack, data_node.x): sd->N;
#else
decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, NULL);
float mix_weight = 1.0f;
uint4 data_node = read_node(kg, offset);
- float3 N = stack_valid(data_node.y)? stack_load_float3(stack, data_node.y): sd->N;
+ float3 N = stack_valid(data_node.x)? stack_load_float3(stack, data_node.x): sd->N;
#endif
float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __uint_as_float(node.z);
@@ -279,10 +279,10 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
sc->N = N;
#ifdef __ANISOTROPIC__
- sc->T = stack_load_float3(stack, data_node.z);
+ sc->T = stack_load_float3(stack, data_node.y);
/* rotate tangent */
- float rotation = stack_load_float(stack, data_node.w);
+ float rotation = stack_load_float(stack, data_node.z);
if(rotation != 0.0f)
sc->T = rotate_around_axis(sc->T, sc->N, rotation * M_2PI_F);
@@ -353,7 +353,9 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
if(sample_weight > 1e-5f && sd->num_closure+2 < MAX_CLOSURE) {
/* radius * scale */
- float3 radius = stack_load_float3(stack, data_node.w)*param1;
+ float3 radius = stack_load_float3(stack, data_node.z)*param1;
+ /* sharpness */
+ float sharpness = stack_load_float(stack, data_node.w);
/* texture color blur */
float texture_blur = param2;
@@ -363,6 +365,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
sc->sample_weight = sample_weight;
sc->data0 = radius.x;
sc->data1 = texture_blur;
+ sc->T.x = sharpness;
#ifdef __OSL__
sc->prim = NULL;
#endif
@@ -378,6 +381,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
sc->sample_weight = sample_weight;
sc->data0 = radius.y;
sc->data1 = texture_blur;
+ sc->T.x = sharpness;
#ifdef __OSL__
sc->prim = NULL;
#endif
@@ -393,6 +397,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
sc->sample_weight = sample_weight;
sc->data0 = radius.z;
sc->data1 = texture_blur;
+ sc->T.x = sharpness;
#ifdef __OSL__
sc->prim = NULL;
#endif
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index a9c17c8bcd5..06acb9e749e 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -1375,7 +1375,7 @@ BsdfNode::BsdfNode(bool scattering_)
}
}
-void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3)
+void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3, ShaderInput *param4)
{
ShaderInput *color_in = input("Color");
ShaderInput *normal_in = input("Normal");
@@ -1394,6 +1394,8 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
compiler.stack_assign(param2);
if(param3)
compiler.stack_assign(param3);
+ if(param4)
+ compiler.stack_assign(param4);
if(normal_in->link)
compiler.stack_assign(normal_in);
@@ -1410,12 +1412,14 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
__float_as_int((param2)? param2->value.x: 0.0f));
if(tangent_in) {
- compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset, tangent_in->stack_offset,
- (param3)? param3->stack_offset: SVM_STACK_INVALID);
+ compiler.add_node(normal_in->stack_offset, tangent_in->stack_offset,
+ (param3)? param3->stack_offset: SVM_STACK_INVALID,
+ (param4)? param4->stack_offset: SVM_STACK_INVALID);
}
else {
- compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset, SVM_STACK_INVALID,
- (param3)? param3->stack_offset: SVM_STACK_INVALID);
+ compiler.add_node(normal_in->stack_offset, SVM_STACK_INVALID,
+ (param3)? param3->stack_offset: SVM_STACK_INVALID,
+ (param4)? param4->stack_offset: SVM_STACK_INVALID);
}
}
@@ -1707,12 +1711,13 @@ SubsurfaceScatteringNode::SubsurfaceScatteringNode()
add_input("Scale", SHADER_SOCKET_FLOAT, 0.01f);
add_input("Radius", SHADER_SOCKET_VECTOR, make_float3(0.1f, 0.1f, 0.1f));
+ add_input("Sharpness", SHADER_SOCKET_FLOAT, 0.0f);
add_input("Texture Blur", SHADER_SOCKET_FLOAT, 1.0f);
}
void SubsurfaceScatteringNode::compile(SVMCompiler& compiler)
{
- BsdfNode::compile(compiler, input("Scale"), input("Texture Blur"), input("Radius"));
+ BsdfNode::compile(compiler, input("Scale"), input("Texture Blur"), input("Radius"), input("Sharpness"));
}
void SubsurfaceScatteringNode::compile(OSLCompiler& compiler)
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 1a2494d96ea..50338ddd5c0 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -203,7 +203,7 @@ public:
BsdfNode(bool scattering = false);
SHADER_NODE_BASE_CLASS(BsdfNode);
- void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL);
+ void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL, ShaderInput *param4 = NULL);
ClosureType closure;
bool scattering;