forked from bartvdbraak/blender
Cycles / SSS:
* Remove the compatible falloff SSS implementation. We shouldn't support two implementations in the long term, and 2.7x is a good release number do break some compatibility as well. * Version patch added, so Files with Compatible falloff will automatically use Cubic now. It was already mentioned in the manual, that Compatible is deprecated. http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/Shaders#BSSRDF
This commit is contained in:
parent
03f7885b0a
commit
e6ce07a5d4
@ -322,9 +322,6 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
|
||||
SubsurfaceScatteringNode *subsurface = new SubsurfaceScatteringNode();
|
||||
|
||||
switch(b_subsurface_node.falloff()) {
|
||||
case BL::ShaderNodeSubsurfaceScattering::falloff_COMPATIBLE:
|
||||
subsurface->closure = CLOSURE_BSSRDF_COMPATIBLE_ID;
|
||||
break;
|
||||
case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
|
||||
subsurface->closure = CLOSURE_BSSRDF_CUBIC_ID;
|
||||
break;
|
||||
|
@ -266,14 +266,9 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
|
||||
if(sc) {
|
||||
uint lcg_state = lcg_init(*rng + rng_offset + sample*0x68bc21eb);
|
||||
|
||||
if(old_subsurface_scatter_use(&sd)) {
|
||||
old_subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, false);
|
||||
}
|
||||
else {
|
||||
float bssrdf_u, bssrdf_v;
|
||||
path_rng_2D(kg, rng, sample, num_total_samples, rng_offset + PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
|
||||
subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false);
|
||||
}
|
||||
|
||||
state.flag |= PATH_RAY_BSSRDF_ANCESTOR;
|
||||
}
|
||||
@ -664,10 +659,6 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
|
||||
if(sc) {
|
||||
uint lcg_state = lcg_init(*rng + rng_offset + sample*0x68bc21eb);
|
||||
|
||||
if(old_subsurface_scatter_use(&sd)) {
|
||||
old_subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, false);
|
||||
}
|
||||
else {
|
||||
ShaderData bssrdf_sd[BSSRDF_MAX_HITS];
|
||||
float bssrdf_u, bssrdf_v;
|
||||
path_rng_2D(kg, rng, sample, num_samples, rng_offset + PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
|
||||
@ -696,11 +687,9 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
|
||||
path_radiance_reset_indirect(&L);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The following code is the same as in kernel_path_integrate_lighting(),
|
||||
@ -1131,17 +1120,6 @@ __device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, int
|
||||
/* do subsurface scatter step with copy of shader data, this will
|
||||
* replace the BSSRDF with a diffuse BSDF closure */
|
||||
for(int j = 0; j < num_samples; j++) {
|
||||
if(old_subsurface_scatter_use(&sd)) {
|
||||
ShaderData bssrdf_sd = sd;
|
||||
old_subsurface_scatter_step(kg, &bssrdf_sd, state.flag, sc, &lcg_state, true);
|
||||
|
||||
/* compute lighting with the BSDF closure */
|
||||
kernel_branched_path_integrate_lighting(kg, rng, sample*num_samples + j,
|
||||
aa_samples*num_samples,
|
||||
&bssrdf_sd, throughput, num_samples_inv,
|
||||
ray_pdf, ray_pdf, state, rng_offset, &L, buffer);
|
||||
}
|
||||
else {
|
||||
ShaderData bssrdf_sd[BSSRDF_MAX_HITS];
|
||||
float bssrdf_u, bssrdf_v;
|
||||
path_rng_2D(kg, &bssrdf_rng, sample*num_samples + j, aa_samples*num_samples, rng_offset + PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
|
||||
@ -1154,7 +1132,6 @@ __device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, int
|
||||
&bssrdf_sd[hit], throughput, num_samples_inv,
|
||||
ray_pdf, ray_pdf, state, rng_offset+PRNG_BOUNCE_NUM, &L, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
state.flag &= ~PATH_RAY_BSSRDF_ANCESTOR;
|
||||
}
|
||||
|
@ -403,164 +403,5 @@ __device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd,
|
||||
subsurface_scatter_setup_diffuse_bsdf(sd, eval, (num_hits > 0), N);
|
||||
}
|
||||
|
||||
|
||||
/* OLD BSSRDF */
|
||||
|
||||
__device float old_bssrdf_sample_distance(KernelGlobals *kg, float radius, float refl, float u)
|
||||
{
|
||||
int table_offset = kernel_data.bssrdf.table_offset;
|
||||
float r = lookup_table_read_2D(kg, u, refl, table_offset, BSSRDF_RADIUS_TABLE_SIZE, BSSRDF_REFL_TABLE_SIZE);
|
||||
|
||||
return r*radius;
|
||||
}
|
||||
|
||||
#ifdef BSSRDF_MULTI_EVAL
|
||||
__device float old_bssrdf_pdf(KernelGlobals *kg, float radius, float refl, float r)
|
||||
{
|
||||
if(r >= radius)
|
||||
return 0.0f;
|
||||
|
||||
/* todo: when we use the real BSSRDF this will need to be divided by the maximum
|
||||
* radius instead of the average radius */
|
||||
float t = r/radius;
|
||||
|
||||
int table_offset = kernel_data.bssrdf.table_offset + BSSRDF_PDF_TABLE_OFFSET;
|
||||
float pdf = lookup_table_read_2D(kg, t, refl, table_offset, BSSRDF_RADIUS_TABLE_SIZE, BSSRDF_REFL_TABLE_SIZE);
|
||||
|
||||
pdf /= radius;
|
||||
|
||||
return pdf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BSSRDF_MULTI_EVAL
|
||||
__device float3 old_subsurface_scatter_multi_eval(KernelGlobals *kg, ShaderData *sd, bool hit, float refl, float *r, int num_r, bool all)
|
||||
{
|
||||
/* compute pdf */
|
||||
float3 eval_sum = make_float3(0.0f, 0.0f, 0.0f);
|
||||
float pdf_sum = 0.0f;
|
||||
float sample_weight_sum = 0.0f;
|
||||
int num_bssrdf = 0;
|
||||
|
||||
for(int i = 0; i < sd->num_closure; i++) {
|
||||
ShaderClosure *sc = &sd->closure[i];
|
||||
|
||||
if(CLOSURE_IS_BSSRDF(sc->type)) {
|
||||
float sample_weight = (all)? 1.0f: sc->sample_weight;
|
||||
|
||||
/* compute pdf */
|
||||
float pdf = 1.0f;
|
||||
for(int i = 0; i < num_r; i++)
|
||||
pdf *= old_bssrdf_pdf(kg, sc->data0, refl, r[i]);
|
||||
|
||||
eval_sum += sc->weight*pdf;
|
||||
pdf_sum += sample_weight*pdf;
|
||||
|
||||
sample_weight_sum += sample_weight;
|
||||
num_bssrdf++;
|
||||
}
|
||||
}
|
||||
|
||||
float inv_pdf_sum;
|
||||
|
||||
if(pdf_sum > 0.0f) {
|
||||
/* in case of branched path integrate we sample all bssrdf's once,
|
||||
* for path trace we pick one, so adjust pdf for that */
|
||||
if(all)
|
||||
inv_pdf_sum = 1.0f/pdf_sum;
|
||||
else
|
||||
inv_pdf_sum = sample_weight_sum/pdf_sum;
|
||||
}
|
||||
else
|
||||
inv_pdf_sum = 0.0f;
|
||||
|
||||
float3 weight = eval_sum * inv_pdf_sum;
|
||||
|
||||
return weight;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* subsurface scattering step, from a point on the surface to another nearby point on the same object */
|
||||
__device void old_subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, int state_flag, ShaderClosure *sc, uint *lcg_state, bool all)
|
||||
{
|
||||
float radius = sc->data0;
|
||||
float refl = max(average(sc->weight)*3.0f, 0.0f);
|
||||
float r = 0.0f;
|
||||
bool hit = false;
|
||||
float3 weight = make_float3(1.0f, 1.0f, 1.0f);
|
||||
#ifdef BSSRDF_MULTI_EVAL
|
||||
float r_attempts[BSSRDF_MAX_ATTEMPTS];
|
||||
#endif
|
||||
int num_attempts;
|
||||
|
||||
/* attempt to find a hit a given number of times before giving up */
|
||||
for(num_attempts = 0; num_attempts < kernel_data.bssrdf.num_attempts; num_attempts++) {
|
||||
/* random numbers for sampling */
|
||||
float u1 = lcg_step_float(lcg_state);
|
||||
float u2 = lcg_step_float(lcg_state);
|
||||
float u3 = lcg_step_float(lcg_state);
|
||||
float u4 = lcg_step_float(lcg_state);
|
||||
float u5 = lcg_step_float(lcg_state);
|
||||
|
||||
r = old_bssrdf_sample_distance(kg, radius, refl, u5);
|
||||
#ifdef BSSRDF_MULTI_EVAL
|
||||
r_attempts[num_attempts] = r;
|
||||
#endif
|
||||
|
||||
float3 p1 = sd->P + sample_uniform_sphere(u1, u2)*r;
|
||||
float3 p2 = sd->P + sample_uniform_sphere(u3, u4)*r;
|
||||
|
||||
/* create ray */
|
||||
Ray ray;
|
||||
ray.P = p1;
|
||||
ray.D = normalize_len(p2 - p1, &ray.t);
|
||||
ray.dP = sd->dP;
|
||||
ray.dD = differential3_zero();
|
||||
ray.time = sd->time;
|
||||
|
||||
/* intersect with the same object. if multiple intersections are
|
||||
* found it will randomly pick one of them */
|
||||
Intersection isect;
|
||||
if(scene_intersect_subsurface(kg, &ray, &isect, sd->object, lcg_state, 1) == 0)
|
||||
continue;
|
||||
|
||||
/* setup new shading point */
|
||||
shader_setup_from_subsurface(kg, sd, &isect, &ray);
|
||||
|
||||
hit = true;
|
||||
num_attempts++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* evaluate subsurface scattering closures */
|
||||
#ifdef BSSRDF_MULTI_EVAL
|
||||
weight *= old_subsurface_scatter_multi_eval(kg, sd, hit, refl, r_attempts, num_attempts, all);
|
||||
#else
|
||||
weight *= sc->weight;
|
||||
#endif
|
||||
|
||||
if(!hit)
|
||||
weight = make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
/* optionally blur colors and bump mapping */
|
||||
float3 N = sd->N;
|
||||
subsurface_color_bump_blur(kg, sd, sd, state_flag, &weight, &N);
|
||||
|
||||
/* replace closures with a single diffuse BSDF */
|
||||
subsurface_scatter_setup_diffuse_bsdf(sd, weight, hit, N);
|
||||
}
|
||||
|
||||
__device bool old_subsurface_scatter_use(ShaderData *sd)
|
||||
{
|
||||
for(int i = 0; i < sd->num_closure; i++) {
|
||||
ShaderClosure *sc = &sd->closure[i];
|
||||
|
||||
if(sc->type == CLOSURE_BSSRDF_COMPATIBLE_ID)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
@ -253,7 +253,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
|
||||
/* disable in case of diffuse ancestor, can't see it well then and
|
||||
* adds considerably noise due to probabilities of continuing path
|
||||
* getting lower and lower */
|
||||
if(sc.type != CLOSURE_BSSRDF_COMPATIBLE_ID && (path_flag & PATH_RAY_DIFFUSE_ANCESTOR))
|
||||
if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
|
||||
bssrdf->radius = make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
/* create one closure for each color channel */
|
||||
|
@ -378,7 +378,6 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
|
||||
#endif
|
||||
|
||||
#ifdef __SUBSURFACE__
|
||||
case CLOSURE_BSSRDF_COMPATIBLE_ID:
|
||||
case CLOSURE_BSSRDF_CUBIC_ID:
|
||||
case CLOSURE_BSSRDF_GAUSSIAN_ID: {
|
||||
ShaderClosure *sc = &sd->closure[sd->num_closure];
|
||||
@ -388,7 +387,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
|
||||
/* disable in case of diffuse ancestor, can't see it well then and
|
||||
* adds considerably noise due to probabilities of continuing path
|
||||
* getting lower and lower */
|
||||
if(type != CLOSURE_BSSRDF_COMPATIBLE_ID && (path_flag & PATH_RAY_DIFFUSE_ANCESTOR))
|
||||
if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
|
||||
param1 = 0.0f;
|
||||
|
||||
if(sample_weight > 1e-5f && sd->num_closure+2 < MAX_CLOSURE) {
|
||||
|
@ -377,7 +377,6 @@ typedef enum ClosureType {
|
||||
CLOSURE_BSDF_TRANSPARENT_ID,
|
||||
|
||||
/* BSSRDF */
|
||||
CLOSURE_BSSRDF_COMPATIBLE_ID,
|
||||
CLOSURE_BSSRDF_CUBIC_ID,
|
||||
CLOSURE_BSSRDF_GAUSSIAN_ID,
|
||||
|
||||
@ -402,7 +401,7 @@ typedef enum ClosureType {
|
||||
#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_HAIR_REFLECTION_ID)
|
||||
#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID)
|
||||
#define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID)
|
||||
#define CLOSURE_IS_BSSRDF(type) (type >= CLOSURE_BSSRDF_COMPATIBLE_ID && type <= CLOSURE_BSSRDF_GAUSSIAN_ID)
|
||||
#define CLOSURE_IS_BSSRDF(type) (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_GAUSSIAN_ID)
|
||||
#define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_ISOTROPIC_ID)
|
||||
#define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID)
|
||||
#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
|
||||
|
@ -42,7 +42,7 @@ extern "C" {
|
||||
* and keep comment above the defines.
|
||||
* Use STRINGIFY() rather than defining with quotes */
|
||||
#define BLENDER_VERSION 269
|
||||
#define BLENDER_SUBVERSION 0
|
||||
#define BLENDER_SUBVERSION 1
|
||||
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
|
||||
#define BLENDER_MINVERSION 262
|
||||
#define BLENDER_MINSUBVERSION 0
|
||||
|
@ -9708,6 +9708,22 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(main, 269, 1)) {
|
||||
/* Removal of Cycles SSS Compatible fallof */
|
||||
FOREACH_NODETREE(main, ntree, id) {
|
||||
if (ntree->type == NTREE_SHADER) {
|
||||
bNode *node;
|
||||
for (node = ntree->nodes.first; node; node = node->next) {
|
||||
if (node->type == SH_NODE_SUBSURFACE_SCATTERING) {
|
||||
if (node->custom1 == SHD_SUBSURFACE_COMPATIBLE) {
|
||||
node->custom1 = SHD_SUBSURFACE_CUBIC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} FOREACH_NODETREE_END
|
||||
}
|
||||
|
||||
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
|
||||
/* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
|
||||
|
||||
|
@ -976,7 +976,7 @@ typedef struct NodeShaderNormalMap {
|
||||
#define SHD_NORMAL_MAP_BLENDER_WORLD 4
|
||||
|
||||
/* subsurface */
|
||||
#define SHD_SUBSURFACE_COMPATIBLE 0
|
||||
#define SHD_SUBSURFACE_COMPATIBLE 0 // Deprecated
|
||||
#define SHD_SUBSURFACE_CUBIC 1
|
||||
#define SHD_SUBSURFACE_GAUSSIAN 2
|
||||
|
||||
|
@ -3699,7 +3699,6 @@ static void def_sh_tangent(StructRNA *srna)
|
||||
static void def_sh_subsurface(StructRNA *srna)
|
||||
{
|
||||
static EnumPropertyItem prop_subsurface_falloff_items[] = {
|
||||
{SHD_SUBSURFACE_COMPATIBLE, "COMPATIBLE", 0, "Compatible", "Subsurface scattering falloff compatible with previous versions"},
|
||||
{SHD_SUBSURFACE_CUBIC, "CUBIC", 0, "Cubic", "Simple cubic falloff function"},
|
||||
{SHD_SUBSURFACE_GAUSSIAN, "GAUSSIAN", 0, "Gaussian", "Normal distribution, multiple can be combined to fit more complex profiles"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
|
Loading…
Reference in New Issue
Block a user