diff options
Diffstat (limited to 'intern/cycles/kernel/svm/svm_closure.h')
-rw-r--r-- | intern/cycles/kernel/svm/svm_closure.h | 176 |
1 files changed, 145 insertions, 31 deletions
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 935504026ef..f378d24463d 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -20,19 +20,34 @@ CCL_NAMESPACE_BEGIN /* Closure Nodes */ -__device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract) +__device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract) { - if(type == CLOSURE_BSDF_REFRACTION_ID) { + if(type == CLOSURE_BSDF_SHARP_GLASS_ID) { + if(refract) { + sc->data0 = eta; + sd->flag |= bsdf_refraction_setup(sc); + } + else + sd->flag |= bsdf_reflection_setup(sc); + } + else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) { + sc->data0 = roughness; + sc->data1 = eta; + if(refract) - bsdf_refraction_setup(sd, sc, eta); + sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc); else - bsdf_reflection_setup(sd, sc); + sd->flag |= bsdf_microfacet_beckmann_setup(sc); } - else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) { - bsdf_microfacet_beckmann_setup(sd, sc, roughness, eta, refract); + else { + sc->data0 = roughness; + sc->data1 = eta; + + if(refract) + sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc); + else + sd->flag |= bsdf_microfacet_ggx_setup(sc); } - else - bsdf_microfacet_ggx_setup(sd, sc, roughness, eta, refract); } __device_inline ShaderClosure *svm_node_closure_get(ShaderData *sd) @@ -57,7 +72,7 @@ __device_inline void svm_node_closure_set_mix_weight(ShaderClosure *sc, float mi #endif } -__device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, float randb, int path_flag) +__device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, float randb, int path_flag, int *offset) { uint type, param1_offset, param2_offset; @@ -66,11 +81,19 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st decode_node_uchar4(node.y, &type, ¶m1_offset, ¶m2_offset, &mix_weight_offset); float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f); + /* note we read this extra node before weight check, so offset is added */ + uint4 data_node = read_node(kg, offset); + if(mix_weight == 0.0f) return; + + float3 N = stack_valid(data_node.y)? stack_load_float3(stack, data_node.y): sd->N; #else decode_node_uchar4(node.y, &type, ¶m1_offset, ¶m2_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; #endif float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __int_as_float(node.z); @@ -79,25 +102,32 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st switch(type) { case CLOSURE_BSDF_DIFFUSE_ID: { ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; svm_node_closure_set_mix_weight(sc, mix_weight); float roughness = param1; - if(roughness == 0.0f) - bsdf_diffuse_setup(sd, sc); - else - bsdf_oren_nayar_setup(sd, sc, roughness); + + if(roughness == 0.0f) { + sd->flag |= bsdf_diffuse_setup(sc); + } + else { + sc->data0 = roughness; + sd->flag |= bsdf_oren_nayar_setup(sc); + } break; } case CLOSURE_BSDF_TRANSLUCENT_ID: { ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; svm_node_closure_set_mix_weight(sc, mix_weight); - bsdf_translucent_setup(sd, sc); + sd->flag |= bsdf_translucent_setup(sc); break; } case CLOSURE_BSDF_TRANSPARENT_ID: { ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; svm_node_closure_set_mix_weight(sc, mix_weight); - bsdf_transparent_setup(sd, sc); + sd->flag |= bsdf_transparent_setup(sc); break; } case CLOSURE_BSDF_REFLECTION_ID: @@ -108,17 +138,17 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st break; #endif ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; + sc->data0 = param1; svm_node_closure_set_mix_weight(sc, mix_weight); - float roughness = param1; - /* setup bsdf */ if(type == CLOSURE_BSDF_REFLECTION_ID) - bsdf_reflection_setup(sd, sc); + sd->flag |= bsdf_reflection_setup(sc); else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) - bsdf_microfacet_beckmann_setup(sd, sc, roughness, 1.0f, false); + sd->flag |= bsdf_microfacet_beckmann_setup(sc); else - bsdf_microfacet_ggx_setup(sd, sc, roughness, 1.0f, false); + sd->flag |= bsdf_microfacet_ggx_setup(sc); break; } @@ -129,40 +159,68 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) break; #endif + ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; + sc->data0 = param1; + svm_node_closure_set_mix_weight(sc, mix_weight); + + float eta = fmaxf(param2, 1.0f + 1e-5f); + sc->data1 = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; + + /* setup bsdf */ + if(type == CLOSURE_BSDF_REFRACTION_ID) + sd->flag |= bsdf_refraction_setup(sc); + else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) + sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc); + else + sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc); + + break; + } + case CLOSURE_BSDF_SHARP_GLASS_ID: + case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID: + case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: { +#ifdef __CAUSTICS_TRICKS__ + if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) + break; +#endif /* index of refraction */ float eta = fmaxf(param2, 1.0f + 1e-5f); eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; /* fresnel */ - float cosNO = dot(sd->N, sd->I); + float cosNO = dot(N, sd->I); float fresnel = fresnel_dielectric_cos(cosNO, eta); float roughness = param1; #ifdef __MULTI_CLOSURE__ /* reflection */ ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; float3 weight = sc->weight; float sample_weight = sc->sample_weight; svm_node_closure_set_mix_weight(sc, mix_weight*fresnel); - svm_node_glossy_setup(sd, sc, type, eta, roughness, false); + svm_node_glass_setup(sd, sc, type, eta, roughness, false); /* refraction */ sc = svm_node_closure_get(sd); + sc->N = N; sc->weight = weight; sc->sample_weight = sample_weight; svm_node_closure_set_mix_weight(sc, mix_weight*(1.0f - fresnel)); - svm_node_glossy_setup(sd, sc, type, eta, roughness, true); + svm_node_glass_setup(sd, sc, type, eta, roughness, true); #else ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; bool refract = (randb > fresnel); svm_node_closure_set_mix_weight(sc, mix_weight); - svm_node_glossy_setup(sd, sc, type, eta, roughness, refract); + svm_node_glass_setup(sd, sc, type, eta, roughness, refract); #endif break; @@ -174,22 +232,41 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st break; #endif ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; + sc->T = stack_load_float3(stack, data_node.z); svm_node_closure_set_mix_weight(sc, mix_weight); - float roughness_u = param1; - float roughness_v = param2; + /* rotate tangent */ + float rotation = stack_load_float(stack, data_node.w); - bsdf_ward_setup(sd, sc, normalize(sd->dPdu), roughness_u, roughness_v); + if(rotation != 0.0f) + sc->T = rotate_around_axis(sc->T, sc->N, rotation * 2.0f * M_PI_F); + + /* compute roughness */ + float roughness = param1; + float anisotropy = clamp(param2, -0.99f, 0.99f); + + if(anisotropy < 0.0f) { + sc->data0 = roughness/(1.0f + anisotropy); + sc->data1 = roughness*(1.0f + anisotropy); + } + else { + sc->data0 = roughness*(1.0f - anisotropy); + sc->data1 = roughness/(1.0f - anisotropy); + } + + sd->flag |= bsdf_ward_setup(sc); break; } #endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: { ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; svm_node_closure_set_mix_weight(sc, mix_weight); /* sigma */ - float sigma = clamp(param1, 0.0f, 1.0f); - bsdf_ashikhmin_velvet_setup(sd, sc, sigma); + sc->data0 = clamp(param1, 0.0f, 1.0f); + sd->flag |= bsdf_ashikhmin_velvet_setup(sc); break; } default: @@ -222,7 +299,7 @@ __device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float * svm_node_closure_set_mix_weight(sc, mix_weight); float density = param1; - volume_transparent_setup(sd, sc, density); + sd->flag |= volume_transparent_setup(sc, density); break; } case CLOSURE_VOLUME_ISOTROPIC_ID: { @@ -230,7 +307,7 @@ __device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float * svm_node_closure_set_mix_weight(sc, mix_weight); float density = param1; - volume_isotropic_setup(sd, sc, density); + sd->flag |= volume_isotropic_setup(sc, density); break; } default: @@ -320,6 +397,34 @@ __device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node) sd->flag |= SD_HOLDOUT; } +__device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, uint4 node) +{ +#ifdef __MULTI_CLOSURE__ + uint mix_weight_offset = node.y; + + if(stack_valid(mix_weight_offset)) { + float mix_weight = stack_load_float(stack, mix_weight_offset); + + if(mix_weight == 0.0f) + return; + + ShaderClosure *sc = svm_node_closure_get(sd); + sc->weight *= mix_weight; + sc->type = CLOSURE_AMBIENT_OCCLUSION_ID; + } + else { + ShaderClosure *sc = svm_node_closure_get(sd); + sc->type = CLOSURE_AMBIENT_OCCLUSION_ID; + } + +#else + ShaderClosure *sc = &sd->closure; + sc->type = CLOSURE_AMBIENT_OCCLUSION_ID; +#endif + + sd->flag |= SD_AO; +} + /* Closure Nodes */ __device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight) @@ -425,5 +530,14 @@ __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused, #endif } +/* (Bump) normal */ + +__device void svm_node_set_normal(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_direction, uint out_normal) +{ + float3 normal = stack_load_float3(stack, in_direction); + sd->N = normal; + stack_store_float3(stack, out_normal, normal); +} + CCL_NAMESPACE_END |