forked from bartvdbraak/blender
Fix #32907: failure rendering a complex node setup, hitting fixed max number
of closures limit. Optimized the code now so it can handle more. Change SVM mix/add closure handling, now we transform the node graph so that the mix weights are fed into the closure nodes directly.
This commit is contained in:
parent
eab58bf994
commit
ceed3ef640
@ -64,11 +64,22 @@ __device_inline ShaderClosure *svm_node_closure_get(ShaderData *sd)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
__device_inline void svm_node_closure_set_mix_weight(ShaderClosure *sc, float mix_weight)
|
__device_inline ShaderClosure *svm_node_closure_get_weight(ShaderData *sd, float mix_weight)
|
||||||
{
|
{
|
||||||
#ifdef __MULTI_CLOSURE__
|
#ifdef __MULTI_CLOSURE__
|
||||||
|
ShaderClosure *sc = &sd->closure[sd->num_closure];
|
||||||
|
|
||||||
sc->weight *= mix_weight;
|
sc->weight *= mix_weight;
|
||||||
sc->sample_weight = fabsf(average(sc->weight));
|
sc->sample_weight = fabsf(average(sc->weight));
|
||||||
|
|
||||||
|
if(sc->sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) {
|
||||||
|
sd->num_closure++;
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
|
return &sd->closure;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,9 +112,10 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
|
|||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case CLOSURE_BSDF_DIFFUSE_ID: {
|
case CLOSURE_BSDF_DIFFUSE_ID: {
|
||||||
ShaderClosure *sc = svm_node_closure_get(sd);
|
ShaderClosure *sc = svm_node_closure_get_weight(sd, mix_weight);
|
||||||
|
|
||||||
|
if(sc) {
|
||||||
sc->N = N;
|
sc->N = N;
|
||||||
svm_node_closure_set_mix_weight(sc, mix_weight);
|
|
||||||
|
|
||||||
float roughness = param1;
|
float roughness = param1;
|
||||||
|
|
||||||
@ -114,20 +126,25 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
|
|||||||
sc->data0 = roughness;
|
sc->data0 = roughness;
|
||||||
sd->flag |= bsdf_oren_nayar_setup(sc);
|
sd->flag |= bsdf_oren_nayar_setup(sc);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CLOSURE_BSDF_TRANSLUCENT_ID: {
|
case CLOSURE_BSDF_TRANSLUCENT_ID: {
|
||||||
ShaderClosure *sc = svm_node_closure_get(sd);
|
ShaderClosure *sc = svm_node_closure_get_weight(sd, mix_weight);
|
||||||
|
|
||||||
|
if(sc) {
|
||||||
sc->N = N;
|
sc->N = N;
|
||||||
svm_node_closure_set_mix_weight(sc, mix_weight);
|
|
||||||
sd->flag |= bsdf_translucent_setup(sc);
|
sd->flag |= bsdf_translucent_setup(sc);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CLOSURE_BSDF_TRANSPARENT_ID: {
|
case CLOSURE_BSDF_TRANSPARENT_ID: {
|
||||||
ShaderClosure *sc = svm_node_closure_get(sd);
|
ShaderClosure *sc = svm_node_closure_get_weight(sd, mix_weight);
|
||||||
|
|
||||||
|
if(sc) {
|
||||||
sc->N = N;
|
sc->N = N;
|
||||||
svm_node_closure_set_mix_weight(sc, mix_weight);
|
|
||||||
sd->flag |= bsdf_transparent_setup(sc);
|
sd->flag |= bsdf_transparent_setup(sc);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CLOSURE_BSDF_REFLECTION_ID:
|
case CLOSURE_BSDF_REFLECTION_ID:
|
||||||
@ -137,10 +154,11 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
|
|||||||
if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
|
if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
ShaderClosure *sc = svm_node_closure_get(sd);
|
ShaderClosure *sc = svm_node_closure_get_weight(sd, mix_weight);
|
||||||
|
|
||||||
|
if(sc) {
|
||||||
sc->N = N;
|
sc->N = N;
|
||||||
sc->data0 = param1;
|
sc->data0 = param1;
|
||||||
svm_node_closure_set_mix_weight(sc, mix_weight);
|
|
||||||
|
|
||||||
/* setup bsdf */
|
/* setup bsdf */
|
||||||
if(type == CLOSURE_BSDF_REFLECTION_ID)
|
if(type == CLOSURE_BSDF_REFLECTION_ID)
|
||||||
@ -149,6 +167,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
|
|||||||
sd->flag |= bsdf_microfacet_beckmann_setup(sc);
|
sd->flag |= bsdf_microfacet_beckmann_setup(sc);
|
||||||
else
|
else
|
||||||
sd->flag |= bsdf_microfacet_ggx_setup(sc);
|
sd->flag |= bsdf_microfacet_ggx_setup(sc);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -159,10 +178,11 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
|
|||||||
if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
|
if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
ShaderClosure *sc = svm_node_closure_get(sd);
|
ShaderClosure *sc = svm_node_closure_get_weight(sd, mix_weight);
|
||||||
|
|
||||||
|
if(sc) {
|
||||||
sc->N = N;
|
sc->N = N;
|
||||||
sc->data0 = param1;
|
sc->data0 = param1;
|
||||||
svm_node_closure_set_mix_weight(sc, mix_weight);
|
|
||||||
|
|
||||||
float eta = fmaxf(param2, 1.0f + 1e-5f);
|
float eta = fmaxf(param2, 1.0f + 1e-5f);
|
||||||
sc->data1 = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
|
sc->data1 = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
|
||||||
@ -174,6 +194,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
|
|||||||
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc);
|
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc);
|
||||||
else
|
else
|
||||||
sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc);
|
sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -195,32 +216,36 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
|
|||||||
|
|
||||||
#ifdef __MULTI_CLOSURE__
|
#ifdef __MULTI_CLOSURE__
|
||||||
/* reflection */
|
/* reflection */
|
||||||
ShaderClosure *sc = svm_node_closure_get(sd);
|
ShaderClosure *sc = &sd->closure[sd->num_closure];
|
||||||
sc->N = N;
|
|
||||||
|
|
||||||
float3 weight = sc->weight;
|
float3 weight = sc->weight;
|
||||||
float sample_weight = sc->sample_weight;
|
float sample_weight = sc->sample_weight;
|
||||||
|
|
||||||
svm_node_closure_set_mix_weight(sc, mix_weight*fresnel);
|
sc = svm_node_closure_get_weight(sd, mix_weight*fresnel);
|
||||||
|
|
||||||
|
if(sc) {
|
||||||
|
sc->N = N;
|
||||||
svm_node_glass_setup(sd, sc, type, eta, roughness, false);
|
svm_node_glass_setup(sd, sc, type, eta, roughness, false);
|
||||||
|
}
|
||||||
|
|
||||||
/* refraction */
|
/* refraction */
|
||||||
sc = svm_node_closure_get(sd);
|
sc = &sd->closure[sd->num_closure];
|
||||||
sc->N = N;
|
|
||||||
|
|
||||||
sc->weight = weight;
|
sc->weight = weight;
|
||||||
sc->sample_weight = sample_weight;
|
sc->sample_weight = sample_weight;
|
||||||
|
|
||||||
svm_node_closure_set_mix_weight(sc, mix_weight*(1.0f - fresnel));
|
sc = svm_node_closure_get_weight(sd, mix_weight*(1.0f - fresnel));
|
||||||
svm_node_glass_setup(sd, sc, type, eta, roughness, true);
|
|
||||||
#else
|
if(sc) {
|
||||||
ShaderClosure *sc = svm_node_closure_get(sd);
|
|
||||||
sc->N = N;
|
sc->N = N;
|
||||||
|
svm_node_glass_setup(sd, sc, type, eta, roughness, true);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ShaderClosure *sc = svm_node_closure_get_weight(sd, mix_weight);
|
||||||
|
|
||||||
|
if(sc) {
|
||||||
|
sc->N = N;
|
||||||
bool refract = (randb > fresnel);
|
bool refract = (randb > fresnel);
|
||||||
|
|
||||||
svm_node_closure_set_mix_weight(sc, mix_weight);
|
|
||||||
svm_node_glass_setup(sd, sc, type, eta, roughness, refract);
|
svm_node_glass_setup(sd, sc, type, eta, roughness, refract);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -230,9 +255,10 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
|
|||||||
if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
|
if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
ShaderClosure *sc = svm_node_closure_get(sd);
|
ShaderClosure *sc = svm_node_closure_get_weight(sd, mix_weight);
|
||||||
|
|
||||||
|
if(sc) {
|
||||||
sc->N = N;
|
sc->N = N;
|
||||||
svm_node_closure_set_mix_weight(sc, mix_weight);
|
|
||||||
|
|
||||||
#ifdef __ANISOTROPIC__
|
#ifdef __ANISOTROPIC__
|
||||||
sc->T = stack_load_float3(stack, data_node.z);
|
sc->T = stack_load_float3(stack, data_node.z);
|
||||||
@ -260,16 +286,19 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
|
|||||||
#else
|
#else
|
||||||
sd->flag |= bsdf_diffuse_setup(sc);
|
sd->flag |= bsdf_diffuse_setup(sc);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
|
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
|
||||||
ShaderClosure *sc = svm_node_closure_get(sd);
|
ShaderClosure *sc = svm_node_closure_get_weight(sd, mix_weight);
|
||||||
|
|
||||||
|
if(sc) {
|
||||||
sc->N = N;
|
sc->N = N;
|
||||||
svm_node_closure_set_mix_weight(sc, mix_weight);
|
|
||||||
|
|
||||||
/* sigma */
|
/* sigma */
|
||||||
sc->data0 = clamp(param1, 0.0f, 1.0f);
|
sc->data0 = clamp(param1, 0.0f, 1.0f);
|
||||||
sd->flag |= bsdf_ashikhmin_velvet_setup(sc);
|
sd->flag |= bsdf_ashikhmin_velvet_setup(sc);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -298,19 +327,21 @@ __device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *
|
|||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case CLOSURE_VOLUME_TRANSPARENT_ID: {
|
case CLOSURE_VOLUME_TRANSPARENT_ID: {
|
||||||
ShaderClosure *sc = svm_node_closure_get(sd);
|
ShaderClosure *sc = svm_node_closure_get_weight(sd, mix_weight);
|
||||||
svm_node_closure_set_mix_weight(sc, mix_weight);
|
|
||||||
|
|
||||||
|
if(sc) {
|
||||||
float density = param1;
|
float density = param1;
|
||||||
sd->flag |= volume_transparent_setup(sc, density);
|
sd->flag |= volume_transparent_setup(sc, density);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CLOSURE_VOLUME_ISOTROPIC_ID: {
|
case CLOSURE_VOLUME_ISOTROPIC_ID: {
|
||||||
ShaderClosure *sc = svm_node_closure_get(sd);
|
ShaderClosure *sc = svm_node_closure_get_weight(sd, mix_weight);
|
||||||
svm_node_closure_set_mix_weight(sc, mix_weight);
|
|
||||||
|
|
||||||
|
if(sc) {
|
||||||
float density = param1;
|
float density = param1;
|
||||||
sd->flag |= volume_isotropic_setup(sc, density);
|
sd->flag |= volume_isotropic_setup(sc, density);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -37,7 +37,7 @@ ShaderInput::ShaderInput(ShaderNode *parent_, const char *name_, ShaderSocketTyp
|
|||||||
value = make_float3(0, 0, 0);
|
value = make_float3(0, 0, 0);
|
||||||
stack_offset = SVM_STACK_INVALID;
|
stack_offset = SVM_STACK_INVALID;
|
||||||
default_value = NONE;
|
default_value = NONE;
|
||||||
osl_only = false;
|
usage = USE_ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderOutput::ShaderOutput(ShaderNode *parent_, const char *name_, ShaderSocketType type_)
|
ShaderOutput::ShaderOutput(ShaderNode *parent_, const char *name_, ShaderSocketType type_)
|
||||||
@ -85,27 +85,29 @@ ShaderOutput *ShaderNode::output(const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value)
|
ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value, int usage)
|
||||||
{
|
{
|
||||||
ShaderInput *input = new ShaderInput(this, name, type);
|
ShaderInput *input = new ShaderInput(this, name, type);
|
||||||
input->value.x = value;
|
input->value.x = value;
|
||||||
|
input->usage = usage;
|
||||||
inputs.push_back(input);
|
inputs.push_back(input);
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value)
|
ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value, int usage)
|
||||||
{
|
{
|
||||||
ShaderInput *input = new ShaderInput(this, name, type);
|
ShaderInput *input = new ShaderInput(this, name, type);
|
||||||
input->value = value;
|
input->value = value;
|
||||||
|
input->usage = usage;
|
||||||
inputs.push_back(input);
|
inputs.push_back(input);
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, bool osl_only)
|
ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, int usage)
|
||||||
{
|
{
|
||||||
ShaderInput *input = add_input(name, type);
|
ShaderInput *input = add_input(name, type);
|
||||||
input->default_value = value;
|
input->default_value = value;
|
||||||
input->osl_only = osl_only;
|
input->usage = usage;
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +221,7 @@ void ShaderGraph::disconnect(ShaderInput *to)
|
|||||||
from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
|
from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderGraph::finalize(bool do_bump, bool do_osl)
|
void ShaderGraph::finalize(bool do_bump, bool do_osl, bool do_multi_transform)
|
||||||
{
|
{
|
||||||
/* before compiling, the shader graph may undergo a number of modifications.
|
/* before compiling, the shader graph may undergo a number of modifications.
|
||||||
* currently we set default geometry shader inputs, and create automatic bump
|
* currently we set default geometry shader inputs, and create automatic bump
|
||||||
@ -234,6 +236,18 @@ void ShaderGraph::finalize(bool do_bump, bool do_osl)
|
|||||||
if(do_bump)
|
if(do_bump)
|
||||||
bump_from_displacement();
|
bump_from_displacement();
|
||||||
|
|
||||||
|
if(do_multi_transform) {
|
||||||
|
ShaderInput *surface_in = output()->input("Surface");
|
||||||
|
ShaderInput *volume_in = output()->input("Volume");
|
||||||
|
|
||||||
|
/* todo: make this work when surface and volume closures are tangled up */
|
||||||
|
|
||||||
|
if(surface_in->link)
|
||||||
|
transform_multi_closure(surface_in->link->parent, NULL, false);
|
||||||
|
if(volume_in->link)
|
||||||
|
transform_multi_closure(volume_in->link->parent, NULL, true);
|
||||||
|
}
|
||||||
|
|
||||||
finalized = true;
|
finalized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -440,7 +454,7 @@ void ShaderGraph::default_inputs(bool do_osl)
|
|||||||
|
|
||||||
foreach(ShaderNode *node, nodes) {
|
foreach(ShaderNode *node, nodes) {
|
||||||
foreach(ShaderInput *input, node->inputs) {
|
foreach(ShaderInput *input, node->inputs) {
|
||||||
if(!input->link && !(input->osl_only && !do_osl)) {
|
if(!input->link && ((input->usage & ShaderInput::USE_SVM) || do_osl)) {
|
||||||
if(input->default_value == ShaderInput::TEXTURE_GENERATED) {
|
if(input->default_value == ShaderInput::TEXTURE_GENERATED) {
|
||||||
if(!texco)
|
if(!texco)
|
||||||
texco = new TextureCoordinateNode();
|
texco = new TextureCoordinateNode();
|
||||||
@ -629,5 +643,81 @@ void ShaderGraph::bump_from_displacement()
|
|||||||
add(pair.second);
|
add(pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume)
|
||||||
|
{
|
||||||
|
/* for SVM in multi closure mode, this transforms the shader mix/add part of
|
||||||
|
* the graph into nodes that feed weights into closure nodes. this is too
|
||||||
|
* avoid building a closure tree and then flattening it, and instead write it
|
||||||
|
* directly to an array */
|
||||||
|
|
||||||
|
if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
|
||||||
|
ShaderInput *fin = node->input("Fac");
|
||||||
|
ShaderInput *cl1in = node->input("Closure1");
|
||||||
|
ShaderInput *cl2in = node->input("Closure2");
|
||||||
|
ShaderOutput *weight1_out, *weight2_out;
|
||||||
|
|
||||||
|
if(fin) {
|
||||||
|
/* mix closure: add node to mix closure weights */
|
||||||
|
ShaderNode *mix_node = add(new MixClosureWeightNode());
|
||||||
|
ShaderInput *fac_in = mix_node->input("Fac");
|
||||||
|
ShaderInput *weight_in = mix_node->input("Weight");
|
||||||
|
|
||||||
|
if(fin->link)
|
||||||
|
connect(fin->link, fac_in);
|
||||||
|
else
|
||||||
|
fac_in->value = fin->value;
|
||||||
|
|
||||||
|
if(weight_out)
|
||||||
|
connect(weight_out, weight_in);
|
||||||
|
|
||||||
|
weight1_out = mix_node->output("Weight1");
|
||||||
|
weight2_out = mix_node->output("Weight2");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* add closure: just pass on any weights */
|
||||||
|
weight1_out = weight_out;
|
||||||
|
weight2_out = weight_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cl1in->link)
|
||||||
|
transform_multi_closure(cl1in->link->parent, weight1_out, volume);
|
||||||
|
if(cl2in->link)
|
||||||
|
transform_multi_closure(cl2in->link->parent, weight2_out, volume);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ShaderInput *weight_in = node->input((volume)? "VolumeMixWeight": "SurfaceMixWeight");
|
||||||
|
|
||||||
|
/* not a closure node? */
|
||||||
|
if(!weight_in)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* already has a weight connected to it? add weights */
|
||||||
|
if(weight_in->link || weight_in->value.x != 0.0f) {
|
||||||
|
ShaderNode *math_node = add(new MathNode());
|
||||||
|
ShaderInput *value1_in = math_node->input("Value1");
|
||||||
|
ShaderInput *value2_in = math_node->input("Value2");
|
||||||
|
|
||||||
|
if(weight_in->link)
|
||||||
|
connect(weight_in->link, value1_in);
|
||||||
|
else
|
||||||
|
value1_in->value = weight_in->value;
|
||||||
|
|
||||||
|
if(weight_out)
|
||||||
|
connect(weight_out, value2_in);
|
||||||
|
else
|
||||||
|
value2_in->value.x = 1.0f;
|
||||||
|
|
||||||
|
weight_out = math_node->output("Value");
|
||||||
|
disconnect(weight_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* connected to closure mix weight */
|
||||||
|
if(weight_out)
|
||||||
|
connect(weight_out, weight_in);
|
||||||
|
else
|
||||||
|
weight_in->value.x += 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|
||||||
|
@ -118,6 +118,12 @@ public:
|
|||||||
NONE
|
NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Usage {
|
||||||
|
USE_SVM = 1,
|
||||||
|
USE_OSL = 2,
|
||||||
|
USE_ALL = USE_SVM|USE_OSL
|
||||||
|
};
|
||||||
|
|
||||||
ShaderInput(ShaderNode *parent, const char *name, ShaderSocketType type);
|
ShaderInput(ShaderNode *parent, const char *name, ShaderSocketType type);
|
||||||
void set(const float3& v) { value = v; }
|
void set(const float3& v) { value = v; }
|
||||||
void set(float f) { value = make_float3(f, 0, 0); }
|
void set(float f) { value = make_float3(f, 0, 0); }
|
||||||
@ -134,7 +140,7 @@ public:
|
|||||||
ustring value_string;
|
ustring value_string;
|
||||||
|
|
||||||
int stack_offset; /* for SVM compiler */
|
int stack_offset; /* for SVM compiler */
|
||||||
bool osl_only;
|
int usage;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Output
|
/* Output
|
||||||
@ -167,9 +173,9 @@ public:
|
|||||||
ShaderInput *input(const char *name);
|
ShaderInput *input(const char *name);
|
||||||
ShaderOutput *output(const char *name);
|
ShaderOutput *output(const char *name);
|
||||||
|
|
||||||
ShaderInput *add_input(const char *name, ShaderSocketType type, float value=0.0f);
|
ShaderInput *add_input(const char *name, ShaderSocketType type, float value=0.0f, int usage=ShaderInput::USE_ALL);
|
||||||
ShaderInput *add_input(const char *name, ShaderSocketType type, float3 value);
|
ShaderInput *add_input(const char *name, ShaderSocketType type, float3 value, int usage=ShaderInput::USE_ALL);
|
||||||
ShaderInput *add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, bool osl_only=false);
|
ShaderInput *add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, int usage=ShaderInput::USE_ALL);
|
||||||
ShaderOutput *add_output(const char *name, ShaderSocketType type);
|
ShaderOutput *add_output(const char *name, ShaderSocketType type);
|
||||||
|
|
||||||
virtual ShaderNode *clone() const = 0;
|
virtual ShaderNode *clone() const = 0;
|
||||||
@ -227,7 +233,7 @@ public:
|
|||||||
void connect(ShaderOutput *from, ShaderInput *to);
|
void connect(ShaderOutput *from, ShaderInput *to);
|
||||||
void disconnect(ShaderInput *to);
|
void disconnect(ShaderInput *to);
|
||||||
|
|
||||||
void finalize(bool do_bump = false, bool do_osl = false);
|
void finalize(bool do_bump = false, bool do_osl = false, bool do_multi_closure = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef pair<ShaderNode* const, ShaderNode*> NodePair;
|
typedef pair<ShaderNode* const, ShaderNode*> NodePair;
|
||||||
@ -241,6 +247,7 @@ protected:
|
|||||||
void bump_from_displacement();
|
void bump_from_displacement();
|
||||||
void refine_bump_nodes();
|
void refine_bump_nodes();
|
||||||
void default_inputs(bool do_osl);
|
void default_inputs(bool do_osl);
|
||||||
|
void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume);
|
||||||
};
|
};
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
@ -1257,6 +1257,7 @@ BsdfNode::BsdfNode()
|
|||||||
|
|
||||||
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
|
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
|
||||||
add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
|
add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
|
||||||
|
add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
|
||||||
|
|
||||||
add_output("BSDF", SHADER_SOCKET_CLOSURE);
|
add_output("BSDF", SHADER_SOCKET_CLOSURE);
|
||||||
}
|
}
|
||||||
@ -1544,6 +1545,8 @@ EmissionNode::EmissionNode()
|
|||||||
|
|
||||||
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
|
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
|
||||||
add_input("Strength", SHADER_SOCKET_FLOAT, 10.0f);
|
add_input("Strength", SHADER_SOCKET_FLOAT, 10.0f);
|
||||||
|
add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
|
||||||
|
|
||||||
add_output("Emission", SHADER_SOCKET_CLOSURE);
|
add_output("Emission", SHADER_SOCKET_CLOSURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1578,6 +1581,8 @@ BackgroundNode::BackgroundNode()
|
|||||||
{
|
{
|
||||||
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
|
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
|
||||||
add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f);
|
add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f);
|
||||||
|
add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
|
||||||
|
|
||||||
add_output("Background", SHADER_SOCKET_CLOSURE);
|
add_output("Background", SHADER_SOCKET_CLOSURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1607,6 +1612,9 @@ void BackgroundNode::compile(OSLCompiler& compiler)
|
|||||||
HoldoutNode::HoldoutNode()
|
HoldoutNode::HoldoutNode()
|
||||||
: ShaderNode("holdout")
|
: ShaderNode("holdout")
|
||||||
{
|
{
|
||||||
|
add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
|
||||||
|
add_input("VolumeMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
|
||||||
|
|
||||||
add_output("Holdout", SHADER_SOCKET_CLOSURE);
|
add_output("Holdout", SHADER_SOCKET_CLOSURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1625,9 +1633,10 @@ void HoldoutNode::compile(OSLCompiler& compiler)
|
|||||||
AmbientOcclusionNode::AmbientOcclusionNode()
|
AmbientOcclusionNode::AmbientOcclusionNode()
|
||||||
: ShaderNode("ambient_occlusion")
|
: ShaderNode("ambient_occlusion")
|
||||||
{
|
{
|
||||||
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
|
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
|
||||||
|
|
||||||
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
|
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
|
||||||
|
add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
|
||||||
|
|
||||||
add_output("AO", SHADER_SOCKET_CLOSURE);
|
add_output("AO", SHADER_SOCKET_CLOSURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1659,6 +1668,7 @@ VolumeNode::VolumeNode()
|
|||||||
|
|
||||||
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
|
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
|
||||||
add_input("Density", SHADER_SOCKET_FLOAT, 1.0f);
|
add_input("Density", SHADER_SOCKET_FLOAT, 1.0f);
|
||||||
|
add_input("VolumeMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
|
||||||
|
|
||||||
add_output("Volume", SHADER_SOCKET_CLOSURE);
|
add_output("Volume", SHADER_SOCKET_CLOSURE);
|
||||||
}
|
}
|
||||||
@ -1737,7 +1747,7 @@ void IsotropicVolumeNode::compile(OSLCompiler& compiler)
|
|||||||
GeometryNode::GeometryNode()
|
GeometryNode::GeometryNode()
|
||||||
: ShaderNode("geometry")
|
: ShaderNode("geometry")
|
||||||
{
|
{
|
||||||
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
|
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
|
||||||
add_output("Position", SHADER_SOCKET_POINT);
|
add_output("Position", SHADER_SOCKET_POINT);
|
||||||
add_output("Normal", SHADER_SOCKET_NORMAL);
|
add_output("Normal", SHADER_SOCKET_NORMAL);
|
||||||
add_output("Tangent", SHADER_SOCKET_NORMAL);
|
add_output("Tangent", SHADER_SOCKET_NORMAL);
|
||||||
@ -1825,7 +1835,7 @@ void GeometryNode::compile(OSLCompiler& compiler)
|
|||||||
TextureCoordinateNode::TextureCoordinateNode()
|
TextureCoordinateNode::TextureCoordinateNode()
|
||||||
: ShaderNode("texture_coordinate")
|
: ShaderNode("texture_coordinate")
|
||||||
{
|
{
|
||||||
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
|
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
|
||||||
add_output("Generated", SHADER_SOCKET_POINT);
|
add_output("Generated", SHADER_SOCKET_POINT);
|
||||||
add_output("Normal", SHADER_SOCKET_NORMAL);
|
add_output("Normal", SHADER_SOCKET_NORMAL);
|
||||||
add_output("UV", SHADER_SOCKET_POINT);
|
add_output("UV", SHADER_SOCKET_POINT);
|
||||||
@ -2315,6 +2325,39 @@ void MixClosureNode::compile(OSLCompiler& compiler)
|
|||||||
compiler.add(this, "node_mix_closure");
|
compiler.add(this, "node_mix_closure");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mix Closure */
|
||||||
|
|
||||||
|
MixClosureWeightNode::MixClosureWeightNode()
|
||||||
|
: ShaderNode("mix_closure_weight")
|
||||||
|
{
|
||||||
|
add_input("Weight", SHADER_SOCKET_FLOAT, 1.0f);
|
||||||
|
add_input("Fac", SHADER_SOCKET_FLOAT, 1.0f);
|
||||||
|
add_output("Weight1", SHADER_SOCKET_FLOAT);
|
||||||
|
add_output("Weight2", SHADER_SOCKET_FLOAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MixClosureWeightNode::compile(SVMCompiler& compiler)
|
||||||
|
{
|
||||||
|
ShaderInput *weight_in = input("Weight");
|
||||||
|
ShaderInput *fac_in = input("Fac");
|
||||||
|
ShaderOutput *weight1_out = output("Weight1");
|
||||||
|
ShaderOutput *weight2_out = output("Weight2");
|
||||||
|
|
||||||
|
compiler.stack_assign(weight_in);
|
||||||
|
compiler.stack_assign(fac_in);
|
||||||
|
compiler.stack_assign(weight1_out);
|
||||||
|
compiler.stack_assign(weight2_out);
|
||||||
|
|
||||||
|
compiler.add_node(NODE_MIX_CLOSURE,
|
||||||
|
compiler.encode_uchar4(fac_in->stack_offset, weight_in->stack_offset,
|
||||||
|
weight1_out->stack_offset, weight2_out->stack_offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MixClosureWeightNode::compile(OSLCompiler& compiler)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Invert */
|
/* Invert */
|
||||||
|
|
||||||
InvertNode::InvertNode()
|
InvertNode::InvertNode()
|
||||||
@ -2680,7 +2723,7 @@ void CameraNode::compile(OSLCompiler& compiler)
|
|||||||
FresnelNode::FresnelNode()
|
FresnelNode::FresnelNode()
|
||||||
: ShaderNode("Fresnel")
|
: ShaderNode("Fresnel")
|
||||||
{
|
{
|
||||||
add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
|
add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
|
||||||
add_input("IOR", SHADER_SOCKET_FLOAT, 1.45f);
|
add_input("IOR", SHADER_SOCKET_FLOAT, 1.45f);
|
||||||
add_output("Fac", SHADER_SOCKET_FLOAT);
|
add_output("Fac", SHADER_SOCKET_FLOAT);
|
||||||
}
|
}
|
||||||
@ -2705,7 +2748,7 @@ void FresnelNode::compile(OSLCompiler& compiler)
|
|||||||
LayerWeightNode::LayerWeightNode()
|
LayerWeightNode::LayerWeightNode()
|
||||||
: ShaderNode("LayerWeight")
|
: ShaderNode("LayerWeight")
|
||||||
{
|
{
|
||||||
add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
|
add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
|
||||||
add_input("Blend", SHADER_SOCKET_FLOAT, 0.5f);
|
add_input("Blend", SHADER_SOCKET_FLOAT, 0.5f);
|
||||||
|
|
||||||
add_output("Fresnel", SHADER_SOCKET_FLOAT);
|
add_output("Fresnel", SHADER_SOCKET_FLOAT);
|
||||||
@ -3080,7 +3123,7 @@ NormalMapNode::NormalMapNode()
|
|||||||
space = ustring("Tangent");
|
space = ustring("Tangent");
|
||||||
attribute = ustring("");
|
attribute = ustring("");
|
||||||
|
|
||||||
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
|
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
|
||||||
add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f);
|
add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f);
|
||||||
add_input("Color", SHADER_SOCKET_COLOR);
|
add_input("Color", SHADER_SOCKET_COLOR);
|
||||||
|
|
||||||
@ -3185,7 +3228,7 @@ TangentNode::TangentNode()
|
|||||||
axis = ustring("X");
|
axis = ustring("X");
|
||||||
attribute = ustring("");
|
attribute = ustring("");
|
||||||
|
|
||||||
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
|
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
|
||||||
add_output("Tangent", SHADER_SOCKET_NORMAL);
|
add_output("Tangent", SHADER_SOCKET_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,6 +351,11 @@ public:
|
|||||||
SHADER_NODE_CLASS(MixClosureNode)
|
SHADER_NODE_CLASS(MixClosureNode)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MixClosureWeightNode : public ShaderNode {
|
||||||
|
public:
|
||||||
|
SHADER_NODE_CLASS(MixClosureWeightNode);
|
||||||
|
};
|
||||||
|
|
||||||
class InvertNode : public ShaderNode {
|
class InvertNode : public ShaderNode {
|
||||||
public:
|
public:
|
||||||
SHADER_NODE_CLASS(InvertNode)
|
SHADER_NODE_CLASS(InvertNode)
|
||||||
|
@ -487,106 +487,30 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SVMCompiler::count_closure_users(ShaderNode *node, map<ShaderNode*, MultiClosureData>& closure_data)
|
void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done)
|
||||||
{
|
|
||||||
/* here we count the number of times each closure node is used, so that
|
|
||||||
* the last time we encounter it we can run the actually code with the
|
|
||||||
* weights from all other places added together */
|
|
||||||
|
|
||||||
if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
|
|
||||||
ShaderInput *cl1in = node->input("Closure1");
|
|
||||||
ShaderInput *cl2in = node->input("Closure2");
|
|
||||||
|
|
||||||
if(cl1in->link)
|
|
||||||
count_closure_users(cl1in->link->parent, closure_data);
|
|
||||||
if(cl2in->link)
|
|
||||||
count_closure_users(cl2in->link->parent, closure_data);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
MultiClosureData data;
|
|
||||||
|
|
||||||
if(closure_data.find(node) == closure_data.end()) {
|
|
||||||
data.stack_offset = SVM_STACK_INVALID;
|
|
||||||
data.users = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data = closure_data[node];
|
|
||||||
data.users++;
|
|
||||||
}
|
|
||||||
|
|
||||||
closure_data[node] = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done,
|
|
||||||
map<ShaderNode*, MultiClosureData>& closure_data, uint in_offset)
|
|
||||||
{
|
{
|
||||||
/* todo: the weaks point here is that unlike the single closure sampling
|
/* todo: the weaks point here is that unlike the single closure sampling
|
||||||
* we will evaluate all nodes even if they are used as input for closures
|
* we will evaluate all nodes even if they are used as input for closures
|
||||||
* that are unused. it's not clear what would be the best way to skip such
|
* that are unused. it's not clear what would be the best way to skip such
|
||||||
* nodes at runtime, especially if they are tangled up */
|
* nodes at runtime, especially if they are tangled up */
|
||||||
|
|
||||||
|
/* only generate once */
|
||||||
|
if(done.find(node) != done.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
done.insert(node);
|
||||||
|
|
||||||
if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
|
if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
|
||||||
ShaderInput *fin = node->input("Fac");
|
/* weighting is already taken care of in ShaderGraph::transform_multi_closure */
|
||||||
ShaderInput *cl1in = node->input("Closure1");
|
ShaderInput *cl1in = node->input("Closure1");
|
||||||
ShaderInput *cl2in = node->input("Closure2");
|
ShaderInput *cl2in = node->input("Closure2");
|
||||||
|
|
||||||
uint out1_offset = SVM_STACK_INVALID;
|
|
||||||
uint out2_offset = SVM_STACK_INVALID;
|
|
||||||
|
|
||||||
if(fin) {
|
|
||||||
/* mix closure */
|
|
||||||
set<ShaderNode*> dependencies;
|
|
||||||
find_dependencies(dependencies, done, fin);
|
|
||||||
generate_svm_nodes(dependencies, done);
|
|
||||||
|
|
||||||
stack_assign(fin);
|
|
||||||
|
|
||||||
if(cl1in->link)
|
if(cl1in->link)
|
||||||
out1_offset = stack_find_offset(SHADER_SOCKET_FLOAT);
|
generate_multi_closure(cl1in->link->parent, done);
|
||||||
if(cl2in->link)
|
if(cl2in->link)
|
||||||
out2_offset = stack_find_offset(SHADER_SOCKET_FLOAT);
|
generate_multi_closure(cl2in->link->parent, done);
|
||||||
|
|
||||||
add_node(NODE_MIX_CLOSURE,
|
|
||||||
encode_uchar4(fin->stack_offset, in_offset, out1_offset, out2_offset));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* add closure */
|
|
||||||
out1_offset = in_offset;
|
|
||||||
out2_offset = in_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(cl1in->link)
|
|
||||||
generate_multi_closure(cl1in->link->parent, done, closure_data, out1_offset);
|
|
||||||
|
|
||||||
if(cl2in->link)
|
|
||||||
generate_multi_closure(cl2in->link->parent, done, closure_data, out2_offset);
|
|
||||||
|
|
||||||
if(in_offset != SVM_STACK_INVALID)
|
|
||||||
stack_clear_offset(SHADER_SOCKET_FLOAT, in_offset);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
MultiClosureData data = closure_data[node];
|
|
||||||
|
|
||||||
if(data.stack_offset == SVM_STACK_INVALID) {
|
|
||||||
/* first time using closure, use stack position for weight */
|
|
||||||
data.stack_offset = in_offset;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* not first time using, add weights together */
|
|
||||||
add_node(NODE_MATH, NODE_MATH_ADD, data.stack_offset, in_offset);
|
|
||||||
add_node(NODE_MATH, data.stack_offset);
|
|
||||||
|
|
||||||
stack_clear_offset(SHADER_SOCKET_FLOAT, in_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
data.users--;
|
|
||||||
closure_data[node] = data;
|
|
||||||
|
|
||||||
/* still users coming? skip generating closure code */
|
|
||||||
if(data.users > 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* execute dependencies for closure */
|
/* execute dependencies for closure */
|
||||||
foreach(ShaderInput *in, node->inputs) {
|
foreach(ShaderInput *in, node->inputs) {
|
||||||
if(!node_skip_input(node, in) && in->link) {
|
if(!node_skip_input(node, in) && in->link) {
|
||||||
@ -596,7 +520,16 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mix_weight_offset = data.stack_offset;
|
/* closure mix weight */
|
||||||
|
const char *weight_name = (current_type == SHADER_TYPE_VOLUME)? "VolumeMixWeight": "SurfaceMixWeight";
|
||||||
|
ShaderInput *weight_in = node->input(weight_name);
|
||||||
|
|
||||||
|
if(weight_in && (weight_in->link || weight_in->value.x != 1.0f)) {
|
||||||
|
stack_assign(weight_in);
|
||||||
|
mix_weight_offset = weight_in->stack_offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mix_weight_offset = SVM_STACK_INVALID;
|
||||||
|
|
||||||
/* compile closure itself */
|
/* compile closure itself */
|
||||||
node->compile(*this);
|
node->compile(*this);
|
||||||
@ -609,11 +542,6 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
|
|||||||
current_shader->has_surface_emission = true;
|
current_shader->has_surface_emission = true;
|
||||||
if(node->name == ustring("transparent"))
|
if(node->name == ustring("transparent"))
|
||||||
current_shader->has_surface_transparent = true;
|
current_shader->has_surface_transparent = true;
|
||||||
|
|
||||||
/* end node is added outside of this */
|
|
||||||
|
|
||||||
if(data.stack_offset != SVM_STACK_INVALID)
|
|
||||||
stack_clear_offset(SHADER_SOCKET_FLOAT, data.stack_offset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,12 +613,8 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
|||||||
if(generate) {
|
if(generate) {
|
||||||
set<ShaderNode*> done;
|
set<ShaderNode*> done;
|
||||||
|
|
||||||
if(use_multi_closure) {
|
if(use_multi_closure)
|
||||||
map<ShaderNode*, MultiClosureData> closure_data;
|
generate_multi_closure(clin->link->parent, done);
|
||||||
|
|
||||||
count_closure_users(clin->link->parent, closure_data);
|
|
||||||
generate_multi_closure(clin->link->parent, done, closure_data, SVM_STACK_INVALID);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
generate_closure(clin->link->parent, done);
|
generate_closure(clin->link->parent, done);
|
||||||
}
|
}
|
||||||
@ -713,9 +637,9 @@ void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int in
|
|||||||
shader->graph_bump = shader->graph->copy();
|
shader->graph_bump = shader->graph->copy();
|
||||||
|
|
||||||
/* finalize */
|
/* finalize */
|
||||||
shader->graph->finalize(false, false);
|
shader->graph->finalize(false, false, use_multi_closure);
|
||||||
if(shader->graph_bump)
|
if(shader->graph_bump)
|
||||||
shader->graph_bump->finalize(true, false);
|
shader->graph_bump->finalize(true, false, use_multi_closure);
|
||||||
|
|
||||||
current_shader = shader;
|
current_shader = shader;
|
||||||
|
|
||||||
|
@ -130,14 +130,7 @@ protected:
|
|||||||
void generate_closure(ShaderNode *node, set<ShaderNode*>& done);
|
void generate_closure(ShaderNode *node, set<ShaderNode*>& done);
|
||||||
|
|
||||||
/* multi closure */
|
/* multi closure */
|
||||||
struct MultiClosureData {
|
void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done);
|
||||||
int stack_offset;
|
|
||||||
int users;
|
|
||||||
};
|
|
||||||
|
|
||||||
void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done,
|
|
||||||
map<ShaderNode*,MultiClosureData>& closure_data, uint in_offset);
|
|
||||||
void count_closure_users(ShaderNode *node, map<ShaderNode*, MultiClosureData>& closure_data);
|
|
||||||
|
|
||||||
/* compile */
|
/* compile */
|
||||||
void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
|
void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
|
||||||
|
Loading…
Reference in New Issue
Block a user