Cycles: per-BSDF normal input and new Bump node.

Each BSDF node now has a Normal input, which can be used to set a custom normal
for the BSDF, for example if you want to have only bump on one of the layers in
a multilayer material.

The Bump node can be used to generate a normal from a scalar value, the same as
what happens when you connect a scalar value to the displacement output.

Documentation has been updated with the latest changes:
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes

Patch by Agustin Benavidez, some implementation tweaks by me.
This commit is contained in:
Brecht Van Lommel
2012-10-10 15:56:43 +00:00
parent e9a61cd29d
commit fe09b24e86
30 changed files with 299 additions and 46 deletions

View File

@@ -402,6 +402,10 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph
node = new ParticleInfoNode(); node = new ParticleInfoNode();
break; break;
} }
case BL::ShaderNode::type_BUMP: {
node = new BumpNode();
break;
}
case BL::ShaderNode::type_TEX_IMAGE: { case BL::ShaderNode::type_TEX_IMAGE: {
BL::ShaderNodeTexImage b_image_node(b_node); BL::ShaderNodeTexImage b_image_node(b_node);
BL::Image b_image(b_image_node.image()); BL::Image b_image(b_image_node.image());

View File

@@ -370,6 +370,7 @@ typedef struct ShaderClosure {
#endif #endif
float data0; float data0;
float data1; float data1;
float3 N;
} ShaderClosure; } ShaderClosure;

View File

@@ -58,7 +58,7 @@ __device void bsdf_ashikhmin_velvet_blur(ShaderClosure *sc, float roughness)
__device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) __device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{ {
float m_invsigma2 = sc->data0; float m_invsigma2 = sc->data0;
float3 m_N = sd->N; float3 m_N = sc->N;
float cosNO = dot(m_N, I); float cosNO = dot(m_N, I);
float cosNI = dot(m_N, omega_in); float cosNI = dot(m_N, omega_in);
@@ -106,7 +106,7 @@ __device float bsdf_ashikhmin_velvet_albedo(const ShaderData *sd, const ShaderCl
__device int bsdf_ashikhmin_velvet_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) __device int bsdf_ashikhmin_velvet_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{ {
float m_invsigma2 = sc->data0; float m_invsigma2 = sc->data0;
float3 m_N = sd->N; float3 m_N = sc->N;
// we are viewing the surface from above - send a ray out with uniform // we are viewing the surface from above - send a ray out with uniform
// distribution over the hemisphere // distribution over the hemisphere

View File

@@ -53,7 +53,7 @@ __device void bsdf_diffuse_blur(ShaderClosure *sc, float roughness)
__device float3 bsdf_diffuse_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) __device float3 bsdf_diffuse_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{ {
float3 m_N = sd->N; float3 m_N = sc->N;
float cos_pi = fmaxf(dot(m_N, omega_in), 0.0f) * M_1_PI_F; float cos_pi = fmaxf(dot(m_N, omega_in), 0.0f) * M_1_PI_F;
*pdf = cos_pi; *pdf = cos_pi;
@@ -72,7 +72,7 @@ __device float bsdf_diffuse_albedo(const ShaderData *sd, const ShaderClosure *sc
__device int bsdf_diffuse_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) __device int bsdf_diffuse_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{ {
float3 m_N = sd->N; float3 m_N = sc->N;
// distribution over the hemisphere // distribution over the hemisphere
sample_cos_hemisphere(m_N, randu, randv, omega_in, pdf); sample_cos_hemisphere(m_N, randu, randv, omega_in, pdf);
@@ -116,7 +116,7 @@ __device float3 bsdf_translucent_eval_reflect(const ShaderData *sd, const Shader
__device float3 bsdf_translucent_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) __device float3 bsdf_translucent_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{ {
float3 m_N = sd->N; float3 m_N = sc->N;
float cos_pi = fmaxf(-dot(m_N, omega_in), 0.0f) * M_1_PI_F; float cos_pi = fmaxf(-dot(m_N, omega_in), 0.0f) * M_1_PI_F;
*pdf = cos_pi; *pdf = cos_pi;
@@ -130,7 +130,7 @@ __device float bsdf_translucent_albedo(const ShaderData *sd, const ShaderClosure
__device int bsdf_translucent_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) __device int bsdf_translucent_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{ {
float3 m_N = sd->N; float3 m_N = sc->N;
// we are viewing the surface from the right side - send a ray out with cosine // we are viewing the surface from the right side - send a ray out with cosine
// distribution over the hemisphere // distribution over the hemisphere

View File

@@ -76,7 +76,7 @@ __device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const Sha
float m_ag = sc->data0; float m_ag = sc->data0;
//float m_eta = sc->data1; //float m_eta = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 m_N = sd->N; float3 m_N = sc->N;
if(m_refractive) return make_float3 (0, 0, 0); if(m_refractive) return make_float3 (0, 0, 0);
float cosNO = dot(m_N, I); float cosNO = dot(m_N, I);
@@ -113,7 +113,7 @@ __device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const Sh
float m_ag = sc->data0; float m_ag = sc->data0;
float m_eta = sc->data1; float m_eta = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 m_N = sd->N; float3 m_N = sc->N;
if(!m_refractive) return make_float3 (0, 0, 0); if(!m_refractive) return make_float3 (0, 0, 0);
float cosNO = dot(m_N, I); float cosNO = dot(m_N, I);
@@ -154,7 +154,7 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur
float m_ag = sc->data0; float m_ag = sc->data0;
float m_eta = sc->data1; float m_eta = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 m_N = sd->N; float3 m_N = sc->N;
float cosNO = dot(m_N, sd->I); float cosNO = dot(m_N, sd->I);
if(cosNO > 0) { if(cosNO > 0) {
@@ -302,7 +302,7 @@ __device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, cons
float m_ab = sc->data0; float m_ab = sc->data0;
//float m_eta = sc->data1; //float m_eta = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 m_N = sd->N; float3 m_N = sc->N;
if(m_refractive) return make_float3 (0, 0, 0); if(m_refractive) return make_float3 (0, 0, 0);
float cosNO = dot(m_N, I); float cosNO = dot(m_N, I);
@@ -341,7 +341,7 @@ __device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, con
float m_ab = sc->data0; float m_ab = sc->data0;
float m_eta = sc->data1; float m_eta = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 m_N = sd->N; float3 m_N = sc->N;
if(!m_refractive) return make_float3 (0, 0, 0); if(!m_refractive) return make_float3 (0, 0, 0);
float cosNO = dot(m_N, I); float cosNO = dot(m_N, I);
@@ -384,7 +384,7 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC
float m_ab = sc->data0; float m_ab = sc->data0;
float m_eta = sc->data1; float m_eta = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 m_N = sd->N; float3 m_N = sc->N;
float cosNO = dot(m_N, sd->I); float cosNO = dot(m_N, sd->I);
if(cosNO > 0) { if(cosNO > 0) {

View File

@@ -57,9 +57,9 @@ __device void bsdf_oren_nayar_blur(ShaderClosure *sc, float roughness)
__device float3 bsdf_oren_nayar_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) __device float3 bsdf_oren_nayar_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{ {
if (dot(sd->N, omega_in) > 0.0f) { if (dot(sc->N, omega_in) > 0.0f) {
*pdf = 0.5f * M_1_PI_F; *pdf = 0.5f * M_1_PI_F;
return bsdf_oren_nayar_get_intensity(sc, sd->N, I, omega_in); return bsdf_oren_nayar_get_intensity(sc, sc->N, I, omega_in);
} }
else { else {
*pdf = 0.0f; *pdf = 0.0f;
@@ -79,15 +79,15 @@ __device float bsdf_oren_nayar_albedo(const ShaderData *sd, const ShaderClosure
__device int bsdf_oren_nayar_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) __device int bsdf_oren_nayar_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{ {
sample_uniform_hemisphere(sd->N, randu, randv, omega_in, pdf); sample_uniform_hemisphere(sc->N, randu, randv, omega_in, pdf);
if (dot(sd->Ng, *omega_in) > 0.0f) { if (dot(sd->Ng, *omega_in) > 0.0f) {
*eval = bsdf_oren_nayar_get_intensity(sc, sd->N, sd->I, *omega_in); *eval = bsdf_oren_nayar_get_intensity(sc, sc->N, sd->I, *omega_in);
#ifdef __RAY_DIFFERENTIALS__ #ifdef __RAY_DIFFERENTIALS__
// TODO: find a better approximation for the bounce // TODO: find a better approximation for the bounce
*domega_in_dx = (2.0f * dot(sd->N, sd->dI.dx)) * sd->N - sd->dI.dx; *domega_in_dx = (2.0f * dot(sc->N, sd->dI.dx)) * sc->N - sd->dI.dx;
*domega_in_dy = (2.0f * dot(sd->N, sd->dI.dy)) * sd->N - sd->dI.dy; *domega_in_dy = (2.0f * dot(sc->N, sd->dI.dy)) * sc->N - sd->dI.dy;
*domega_in_dx *= 125.0f; *domega_in_dx *= 125.0f;
*domega_in_dy *= 125.0f; *domega_in_dy *= 125.0f;
#endif #endif

View File

@@ -69,7 +69,7 @@ __device float bsdf_reflection_albedo(const ShaderData *sd, const ShaderClosure
__device int bsdf_reflection_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) __device int bsdf_reflection_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{ {
//const BsdfReflectionClosure *self = (const BsdfReflectionClosure*)sc->data; //const BsdfReflectionClosure *self = (const BsdfReflectionClosure*)sc->data;
float3 m_N = sd->N; float3 m_N = sc->N;
// only one direction is possible // only one direction is possible
float cosNO = dot(m_N, sd->I); float cosNO = dot(m_N, sd->I);

View File

@@ -71,7 +71,7 @@ __device float bsdf_refraction_albedo(const ShaderData *sd, const ShaderClosure
__device int bsdf_refraction_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) __device int bsdf_refraction_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{ {
float m_eta = sc->data0; float m_eta = sc->data0;
float3 m_N = sd->N; float3 m_N = sc->N;
float3 R, T; float3 R, T;
#ifdef __RAY_DIFFERENTIALS__ #ifdef __RAY_DIFFERENTIALS__

View File

@@ -66,7 +66,7 @@ __device float3 bsdf_ward_eval_reflect(const ShaderData *sd, const ShaderClosure
{ {
float m_ax = sc->data0; float m_ax = sc->data0;
float m_ay = sc->data1; float m_ay = sc->data1;
float3 m_N = sd->N; float3 m_N = sc->N;
float3 m_T = sd->T; float3 m_T = sd->T;
float cosNO = dot(m_N, I); float cosNO = dot(m_N, I);
@@ -108,7 +108,7 @@ __device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, flo
{ {
float m_ax = sc->data0; float m_ax = sc->data0;
float m_ay = sc->data1; float m_ay = sc->data1;
float3 m_N = sd->N; float3 m_N = sc->N;
float3 m_T = sd->T; float3 m_T = sd->T;
float cosNO = dot(m_N, sd->I); float cosNO = dot(m_N, sd->I);

View File

@@ -62,7 +62,7 @@ __device void bsdf_westin_backscatter_blur(ShaderClosure *sc, float roughness)
__device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) __device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{ {
float m_invroughness = sc->data0; float m_invroughness = sc->data0;
float3 m_N = sd->N; float3 m_N = sc->N;
// pdf is implicitly 0 (no indirect sampling) // pdf is implicitly 0 (no indirect sampling)
float cosNO = dot(m_N, I); float cosNO = dot(m_N, I);
@@ -89,7 +89,7 @@ __device float bsdf_westin_backscatter_albedo(const ShaderData *sd, const Shader
__device int bsdf_westin_backscatter_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) __device int bsdf_westin_backscatter_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{ {
float m_invroughness = sc->data0; float m_invroughness = sc->data0;
float3 m_N = sd->N; float3 m_N = sc->N;
float cosNO = dot(m_N, sd->I); float cosNO = dot(m_N, sd->I);
if(cosNO > 0) { if(cosNO > 0) {
@@ -151,7 +151,7 @@ __device void bsdf_westin_sheen_blur(ShaderClosure *sc, float roughness)
__device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) __device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{ {
float m_edginess = sc->data0; float m_edginess = sc->data0;
float3 m_N = sd->N; float3 m_N = sc->N;
// pdf is implicitly 0 (no indirect sampling) // pdf is implicitly 0 (no indirect sampling)
float cosNO = dot(m_N, I); float cosNO = dot(m_N, I);
@@ -178,7 +178,7 @@ __device float bsdf_westin_sheen_albedo(const ShaderData *sd, const ShaderClosur
__device int bsdf_westin_sheen_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) __device int bsdf_westin_sheen_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{ {
float m_edginess = sc->data0; float m_edginess = sc->data0;
float3 m_N = sd->N; float3 m_N = sc->N;
// we are viewing the surface from the right side - send a ray out with cosine // we are viewing the surface from the right side - send a ray out with cosine
// distribution over the hemisphere // distribution over the hemisphere

View File

@@ -185,7 +185,7 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
break; break;
} }
case NODE_CLOSURE_BSDF: case NODE_CLOSURE_BSDF:
svm_node_closure_bsdf(kg, sd, stack, node, randb, path_flag); svm_node_closure_bsdf(kg, sd, stack, node, randb, path_flag, &offset);
break; break;
case NODE_CLOSURE_EMISSION: case NODE_CLOSURE_EMISSION:
svm_node_closure_emission(sd, stack, node); svm_node_closure_emission(sd, stack, node);
@@ -342,7 +342,7 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
svm_node_set_displacement(sd, stack, node.y); svm_node_set_displacement(sd, stack, node.y);
break; break;
case NODE_SET_BUMP: case NODE_SET_BUMP:
svm_node_set_bump(sd, stack, node.y, node.z, node.w); svm_node_set_bump(kg, sd, stack, node);
break; break;
case NODE_MATH: case NODE_MATH:
svm_node_math(kg, sd, stack, node.y, node.z, node.w, &offset); svm_node_math(kg, sd, stack, node.y, node.z, node.w, &offset);
@@ -370,6 +370,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
case NODE_TEX_COORD_BUMP_DY: case NODE_TEX_COORD_BUMP_DY:
svm_node_tex_coord_bump_dy(kg, sd, stack, node.y, node.z); svm_node_tex_coord_bump_dy(kg, sd, stack, node.y, node.z);
break; break;
case NODE_CLOSURE_SET_NORMAL:
svm_node_set_normal(kg, sd, stack, node.y, node.z );
break;
#endif #endif
case NODE_EMISSION_SET_WEIGHT_TOTAL: case NODE_EMISSION_SET_WEIGHT_TOTAL:
svm_node_emission_set_weight_total(kg, sd, node.y, node.z, node.w); svm_node_emission_set_weight_total(kg, sd, node.y, node.z, node.w);
@@ -384,7 +387,7 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
case NODE_LIGHT_FALLOFF: case NODE_LIGHT_FALLOFF:
svm_node_light_falloff(sd, stack, node); svm_node_light_falloff(sd, stack, node);
break; break;
#endif #endif
case NODE_END: case NODE_END:
default: default:
#ifndef __MULTI_CLOSURE__ #ifndef __MULTI_CLOSURE__

View File

@@ -57,7 +57,7 @@ __device_inline void svm_node_closure_set_mix_weight(ShaderClosure *sc, float mi
#endif #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; uint type, param1_offset, param2_offset;
@@ -66,11 +66,19 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset); decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset);
float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f); 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) if(mix_weight == 0.0f)
return; return;
float3 N = stack_valid(data_node.y)? stack_load_float3(stack, data_node.y): sd->N;
#else #else
decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, NULL); decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, NULL);
float mix_weight = 1.0f; 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 #endif
float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __int_as_float(node.z); float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __int_as_float(node.z);
@@ -79,6 +87,7 @@ __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(sd);
sc->N = N;
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
float roughness = param1; float roughness = param1;
@@ -90,12 +99,14 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
} }
case CLOSURE_BSDF_TRANSLUCENT_ID: { case CLOSURE_BSDF_TRANSLUCENT_ID: {
ShaderClosure *sc = svm_node_closure_get(sd); ShaderClosure *sc = svm_node_closure_get(sd);
sc->N = N;
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
bsdf_translucent_setup(sd, sc); bsdf_translucent_setup(sd, 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(sd);
sc->N = N;
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
bsdf_transparent_setup(sd, sc); bsdf_transparent_setup(sd, sc);
break; break;
@@ -108,6 +119,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
break; break;
#endif #endif
ShaderClosure *sc = svm_node_closure_get(sd); ShaderClosure *sc = svm_node_closure_get(sd);
sc->N = N;
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
float roughness = param1; float roughness = param1;
@@ -134,13 +146,14 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
/* fresnel */ /* fresnel */
float cosNO = dot(sd->N, sd->I); float cosNO = dot(N, sd->I);
float fresnel = fresnel_dielectric_cos(cosNO, eta); float fresnel = fresnel_dielectric_cos(cosNO, eta);
float roughness = param1; float roughness = param1;
#ifdef __MULTI_CLOSURE__ #ifdef __MULTI_CLOSURE__
/* reflection */ /* reflection */
ShaderClosure *sc = svm_node_closure_get(sd); ShaderClosure *sc = svm_node_closure_get(sd);
sc->N = N;
float3 weight = sc->weight; float3 weight = sc->weight;
float sample_weight = sc->sample_weight; float sample_weight = sc->sample_weight;
@@ -150,6 +163,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
/* refraction */ /* refraction */
sc = svm_node_closure_get(sd); sc = svm_node_closure_get(sd);
sc->N = N;
sc->weight = weight; sc->weight = weight;
sc->sample_weight = sample_weight; sc->sample_weight = sample_weight;
@@ -158,6 +172,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
svm_node_glossy_setup(sd, sc, type, eta, roughness, true); svm_node_glossy_setup(sd, sc, type, eta, roughness, true);
#else #else
ShaderClosure *sc = svm_node_closure_get(sd); ShaderClosure *sc = svm_node_closure_get(sd);
sc->N = N;
bool refract = (randb > fresnel); bool refract = (randb > fresnel);
@@ -174,17 +189,19 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
break; break;
#endif #endif
ShaderClosure *sc = svm_node_closure_get(sd); ShaderClosure *sc = svm_node_closure_get(sd);
sc->N = N;
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
float roughness_u = param1; float roughness_u = param1;
float roughness_v = param2; float roughness_v = param2;
bsdf_ward_setup(sd, sc, normalize(sd->T), roughness_u, roughness_v); bsdf_ward_setup(sd, sc, sd->T, roughness_u, roughness_v);
break; break;
} }
#endif #endif
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(sd);
sc->N = N;
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
/* sigma */ /* sigma */
@@ -425,6 +442,8 @@ __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused,
#endif #endif
} }
/* Tangent */
#ifdef __DPDU__ #ifdef __DPDU__
__device_inline void svm_node_closure_store_tangent(ShaderData *sd, float3 tangent) __device_inline void svm_node_closure_store_tangent(ShaderData *sd, float3 tangent)
{ {
@@ -444,5 +463,14 @@ __device void svm_node_closure_tangent(ShaderData *sd, float *stack, uint tangen
} }
#endif #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 CCL_NAMESPACE_END

View File

@@ -20,23 +20,35 @@ CCL_NAMESPACE_BEGIN
/* Bump Node */ /* Bump Node */
__device void svm_node_set_bump(ShaderData *sd, float *stack, uint c_offset, uint x_offset, uint y_offset) __device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{ {
#ifdef __RAY_DIFFERENTIALS__ #ifdef __RAY_DIFFERENTIALS__
/* get normal input */
float3 normal_in = stack_valid(node.y)? stack_load_float3(stack, node.y): sd->N;
/* get surface tangents from normal */
float3 Rx = cross(sd->dP.dy, normal_in);
float3 Ry = cross(normal_in, sd->dP.dx);
/* get bump values */
uint c_offset, x_offset, y_offset, intensity_offset;
decode_node_uchar4(node.z, &c_offset, &x_offset, &y_offset, &intensity_offset);
float h_c = stack_load_float(stack, c_offset); float h_c = stack_load_float(stack, c_offset);
float h_x = stack_load_float(stack, x_offset); float h_x = stack_load_float(stack, x_offset);
float h_y = stack_load_float(stack, y_offset); float h_y = stack_load_float(stack, y_offset);
float3 Rx = cross(sd->dP.dy, sd->N); /* compute surface gradient and determinant */
float3 Ry = cross(sd->N, sd->dP.dx);
float det = dot(sd->dP.dx, Rx); float det = dot(sd->dP.dx, Rx);
float3 surfgrad = (h_x - h_c)*Rx + (h_y - h_c)*Ry; float3 surfgrad = (h_x - h_c)*Rx + (h_y - h_c)*Ry;
float intensity = stack_load_float(stack, intensity_offset);
surfgrad *= 0.1f; /* todo: remove this factor */ surfgrad *= intensity;
float absdet = fabsf(det); float absdet = fabsf(det);
sd->N = normalize(absdet*sd->N - signf(det)*surfgrad);
/* compute and output perturbed normal */
float3 outN = normalize(absdet*normal_in - signf(det)*surfgrad);
stack_store_float3(stack, node.w, outN);
#endif #endif
} }

View File

@@ -95,6 +95,7 @@ typedef enum NodeType {
NODE_TEX_BRICK, NODE_TEX_BRICK,
NODE_CLOSURE_SET_TANGENT, NODE_CLOSURE_SET_TANGENT,
NODE_CLOSURE_TANGENT, NODE_CLOSURE_TANGENT,
NODE_CLOSURE_SET_NORMAL,
} NodeType; } NodeType;
typedef enum NodeAttributeType { typedef enum NodeAttributeType {

View File

@@ -229,6 +229,8 @@ void ShaderGraph::finalize(bool do_bump, bool do_osl)
if(!finalized) { if(!finalized) {
clean(); clean();
default_inputs(do_osl); default_inputs(do_osl);
refine_bump_nodes();
if(do_bump) if(do_bump)
bump_from_displacement(); bump_from_displacement();
@@ -484,6 +486,61 @@ void ShaderGraph::default_inputs(bool do_osl)
add(texco); add(texco);
} }
void ShaderGraph::refine_bump_nodes()
{
/* we transverse the node graph looking for bump nodes, when we find them,
* like in bump_from_displacement(), we copy the sub-graph defined from "bump"
* input to the inputs "center","dx" and "dy" What is in "bump" input is moved
* to "center" input. */
foreach(ShaderNode *node, nodes) {
if(node->name == ustring("bump") && node->input("Height")->link) {
ShaderInput *bump_input = node->input("Height");
set<ShaderNode*> nodes_bump;
/* make 2 extra copies of the subgraph defined in Bump input */
map<ShaderNode*, ShaderNode*> nodes_dx;
map<ShaderNode*, ShaderNode*> nodes_dy;
/* find dependencies for the given input */
find_dependencies(nodes_bump, bump_input );
copy_nodes(nodes_bump, nodes_dx);
copy_nodes(nodes_bump, nodes_dy);
/* mark nodes to indicate they are use for bump computation, so
that any texture coordinates are shifted by dx/dy when sampling */
foreach(ShaderNode *node, nodes_bump)
node->bump = SHADER_BUMP_CENTER;
foreach(NodePair& pair, nodes_dx)
pair.second->bump = SHADER_BUMP_DX;
foreach(NodePair& pair, nodes_dy)
pair.second->bump = SHADER_BUMP_DY;
ShaderOutput *out = bump_input->link;
ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name);
ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name);
connect(out_dx, node->input("SampleX"));
connect(out_dy, node->input("SampleY"));
/* add generated nodes */
foreach(NodePair& pair, nodes_dx)
add(pair.second);
foreach(NodePair& pair, nodes_dy)
add(pair.second);
/* connect what is conected is bump to samplecenter input*/
connect(out , node->input("SampleCenter"));
/* bump input is just for connectivity purpose for the graph input,
* we reconected this input to samplecenter, so lets disconnect it
* from bump input */
disconnect(bump_input);
}
}
}
void ShaderGraph::bump_from_displacement() void ShaderGraph::bump_from_displacement()
{ {
/* generate bump mapping automatically from displacement. bump mapping is /* generate bump mapping automatically from displacement. bump mapping is
@@ -497,7 +554,7 @@ void ShaderGraph::bump_from_displacement()
* different shifted coordinates. * different shifted coordinates.
* *
* these 3 displacement values are then fed into the bump node, which will * these 3 displacement values are then fed into the bump node, which will
* modify the normal. */ * output the the perturbed normal. */
ShaderInput *displacement_in = output()->input("Displacement"); ShaderInput *displacement_in = output()->input("Displacement");
@@ -526,6 +583,12 @@ void ShaderGraph::bump_from_displacement()
foreach(NodePair& pair, nodes_dy) foreach(NodePair& pair, nodes_dy)
pair.second->bump = SHADER_BUMP_DY; pair.second->bump = SHADER_BUMP_DY;
/* add set normal node and connect the bump normal ouput to the set normal
* output, so it can finally set the shader normal, note we are only doing
* this for bump from displacement, this will be the only bump allowed to
* overwrite the shader normal */
ShaderNode *set_normal = add(new SetNormalNode());
/* add bump node and connect copied graphs to it */ /* add bump node and connect copied graphs to it */
ShaderNode *bump = add(new BumpNode()); ShaderNode *bump = add(new BumpNode());
@@ -537,6 +600,9 @@ void ShaderGraph::bump_from_displacement()
connect(out_center, bump->input("SampleCenter")); connect(out_center, bump->input("SampleCenter"));
connect(out_dx, bump->input("SampleX")); connect(out_dx, bump->input("SampleX"));
connect(out_dy, bump->input("SampleY")); connect(out_dy, bump->input("SampleY"));
/* connect the bump out to the set normal in: */
connect(bump->output("Normal"), set_normal->input("Direction"));
/* connect bump output to normal input nodes that aren't set yet. actually /* connect bump output to normal input nodes that aren't set yet. actually
* this will only set the normal input to the geometry node that we created * this will only set the normal input to the geometry node that we created
@@ -544,8 +610,14 @@ void ShaderGraph::bump_from_displacement()
foreach(ShaderNode *node, nodes) foreach(ShaderNode *node, nodes)
foreach(ShaderInput *input, node->inputs) foreach(ShaderInput *input, node->inputs)
if(!input->link && input->default_value == ShaderInput::NORMAL) if(!input->link && input->default_value == ShaderInput::NORMAL)
connect(bump->output("Normal"), input); connect(set_normal->output("Normal"), input);
/* for displacement bump, clear the normal input in case the above loop
* connected the setnormal out to the bump normalin */
ShaderInput *bump_normal_in = bump->input("NormalIn");
if(bump_normal_in)
bump_normal_in->link = NULL;
/* finally, add the copied nodes to the graph. we can't do this earlier /* finally, add the copied nodes to the graph. we can't do this earlier
* because we would create dependency cycles in the above loop */ * because we would create dependency cycles in the above loop */
foreach(NodePair& pair, nodes_center) foreach(NodePair& pair, nodes_center)

View File

@@ -235,6 +235,7 @@ protected:
void break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack); void break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack);
void clean(); void clean();
void bump_from_displacement(); void bump_from_displacement();
void refine_bump_nodes();
void default_inputs(bool do_osl); void default_inputs(bool do_osl);
}; };

View File

@@ -1175,7 +1175,7 @@ BsdfNode::BsdfNode()
closure = ccl::CLOSURE_BSDF_DIFFUSE_ID; closure = ccl::CLOSURE_BSDF_DIFFUSE_ID;
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, true); add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
add_output("BSDF", SHADER_SOCKET_CLOSURE); add_output("BSDF", SHADER_SOCKET_CLOSURE);
} }
@@ -1183,6 +1183,7 @@ BsdfNode::BsdfNode()
void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2) void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2)
{ {
ShaderInput *color_in = input("Color"); ShaderInput *color_in = input("Color");
ShaderInput *normal_in = input("Normal");
if(color_in->link) { if(color_in->link) {
compiler.stack_assign(color_in); compiler.stack_assign(color_in);
@@ -1203,6 +1204,10 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
compiler.closure_mix_weight_offset()), compiler.closure_mix_weight_offset()),
__float_as_int((param1)? param1->value.x: 0.0f), __float_as_int((param1)? param1->value.x: 0.0f),
__float_as_int((param2)? param2->value.x: 0.0f)); __float_as_int((param2)? param2->value.x: 0.0f));
if(normal_in->link)
compiler.stack_assign(normal_in);
compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset);
} }
void BsdfNode::compile(SVMCompiler& compiler) void BsdfNode::compile(SVMCompiler& compiler)
@@ -2215,7 +2220,7 @@ static ShaderEnum mix_type_init()
enm.insert("Burn", NODE_MIX_BURN); enm.insert("Burn", NODE_MIX_BURN);
enm.insert("Hue", NODE_MIX_HUE); enm.insert("Hue", NODE_MIX_HUE);
enm.insert("Saturation", NODE_MIX_SAT); enm.insert("Saturation", NODE_MIX_SAT);
enm.insert("Value", NODE_MIX_VAL ); enm.insert("Value", NODE_MIX_VAL);
enm.insert("Color", NODE_MIX_COLOR); enm.insert("Color", NODE_MIX_COLOR);
enm.insert("Soft Light", NODE_MIX_SOFT); enm.insert("Soft Light", NODE_MIX_SOFT);
enm.insert("Linear Light", NODE_MIX_LINEAR); enm.insert("Linear Light", NODE_MIX_LINEAR);
@@ -2586,6 +2591,7 @@ OutputNode::OutputNode()
add_input("Surface", SHADER_SOCKET_CLOSURE); add_input("Surface", SHADER_SOCKET_CLOSURE);
add_input("Volume", SHADER_SOCKET_CLOSURE); add_input("Volume", SHADER_SOCKET_CLOSURE);
add_input("Displacement", SHADER_SOCKET_FLOAT); add_input("Displacement", SHADER_SOCKET_FLOAT);
add_input("Normal", SHADER_SOCKET_NORMAL);
} }
void OutputNode::compile(SVMCompiler& compiler) void OutputNode::compile(SVMCompiler& compiler)
@@ -2733,9 +2739,15 @@ void VectorMathNode::compile(OSLCompiler& compiler)
BumpNode::BumpNode() BumpNode::BumpNode()
: ShaderNode("bump") : ShaderNode("bump")
{ {
/* this input is used by the user, but after graph transform it is no longer
* used and moved to sampler center/x/y instead */
add_input("Height", SHADER_SOCKET_NORMAL);
add_input("SampleCenter", SHADER_SOCKET_FLOAT); add_input("SampleCenter", SHADER_SOCKET_FLOAT);
add_input("SampleX", SHADER_SOCKET_FLOAT); add_input("SampleX", SHADER_SOCKET_FLOAT);
add_input("SampleY", SHADER_SOCKET_FLOAT); add_input("SampleY", SHADER_SOCKET_FLOAT);
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
add_input("Strength", SHADER_SOCKET_FLOAT, 0.1f);
add_output("Normal", SHADER_SOCKET_NORMAL); add_output("Normal", SHADER_SOCKET_NORMAL);
} }
@@ -2745,12 +2757,25 @@ void BumpNode::compile(SVMCompiler& compiler)
ShaderInput *center_in = input("SampleCenter"); ShaderInput *center_in = input("SampleCenter");
ShaderInput *dx_in = input("SampleX"); ShaderInput *dx_in = input("SampleX");
ShaderInput *dy_in = input("SampleY"); ShaderInput *dy_in = input("SampleY");
ShaderInput *normal_in = input("NormalIn");
ShaderInput *intensity_in = input("Strength");
ShaderOutput *normal_out = output("Normal");
compiler.stack_assign(center_in); compiler.stack_assign(center_in);
compiler.stack_assign(dx_in); compiler.stack_assign(dx_in);
compiler.stack_assign(dy_in); compiler.stack_assign(dy_in);
compiler.stack_assign(intensity_in);
compiler.stack_assign(normal_out);
compiler.add_node(NODE_SET_BUMP, center_in->stack_offset, dx_in->stack_offset, dy_in->stack_offset); if(normal_in->link)
compiler.stack_assign(normal_in);
/* pack all parameters in the node */
compiler.add_node(NODE_SET_BUMP,
normal_in->stack_offset,
compiler.encode_uchar4(center_in->stack_offset, dx_in->stack_offset,
dy_in->stack_offset, intensity_in->stack_offset),
normal_out->stack_offset);
} }
void BumpNode::compile(OSLCompiler& compiler) void BumpNode::compile(OSLCompiler& compiler)
@@ -2819,17 +2844,44 @@ void RGBRampNode::compile(OSLCompiler& compiler)
/* NB: cycles float3 type is actually 4 floats! need to use an explicit array */ /* NB: cycles float3 type is actually 4 floats! need to use an explicit array */
float ramp_color[RAMP_TABLE_SIZE][3]; float ramp_color[RAMP_TABLE_SIZE][3];
float ramp_alpha[RAMP_TABLE_SIZE]; float ramp_alpha[RAMP_TABLE_SIZE];
for (int i = 0; i < RAMP_TABLE_SIZE; ++i) { for (int i = 0; i < RAMP_TABLE_SIZE; ++i) {
ramp_color[i][0] = ramp[i].x; ramp_color[i][0] = ramp[i].x;
ramp_color[i][1] = ramp[i].y; ramp_color[i][1] = ramp[i].y;
ramp_color[i][2] = ramp[i].z; ramp_color[i][2] = ramp[i].z;
ramp_alpha[i] = ramp[i].w; ramp_alpha[i] = ramp[i].w;
} }
compiler.parameter_color_array("ramp_color", ramp_color, RAMP_TABLE_SIZE); compiler.parameter_color_array("ramp_color", ramp_color, RAMP_TABLE_SIZE);
compiler.parameter_array("ramp_alpha", ramp_alpha, RAMP_TABLE_SIZE); compiler.parameter_array("ramp_alpha", ramp_alpha, RAMP_TABLE_SIZE);
compiler.add(this, "node_rgb_ramp"); compiler.add(this, "node_rgb_ramp");
} }
/* Set Normal Node */
SetNormalNode::SetNormalNode()
: ShaderNode("set_normal")
{
add_input("Direction", SHADER_SOCKET_VECTOR);
add_output("Normal", SHADER_SOCKET_NORMAL);
}
void SetNormalNode::compile(SVMCompiler& compiler)
{
ShaderInput *direction_in = input("Direction");
ShaderOutput *normal_out = output("Normal");
compiler.stack_assign(direction_in);
compiler.stack_assign(normal_out);
compiler.add_node(NODE_CLOSURE_SET_NORMAL, direction_in->stack_offset, normal_out->stack_offset);
}
void SetNormalNode::compile(OSLCompiler& compiler)
{
compiler.add(this, "set_normal");
}
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -440,6 +440,11 @@ public:
float4 ramp[RAMP_TABLE_SIZE]; float4 ramp[RAMP_TABLE_SIZE];
}; };
class SetNormalNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SetNormalNode)
};
CCL_NAMESPACE_END CCL_NAMESPACE_END
#endif /* __NODES_H__ */ #endif /* __NODES_H__ */

View File

@@ -551,6 +551,7 @@ struct ShadeResult;
#define SH_NODE_OBJECT_INFO 167 #define SH_NODE_OBJECT_INFO 167
#define SH_NODE_PARTICLE_INFO 168 #define SH_NODE_PARTICLE_INFO 168
#define SH_NODE_TEX_BRICK 169 #define SH_NODE_TEX_BRICK 169
#define SH_NODE_BUMP 170
/* custom defines options for Material node */ /* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1 #define SH_NODE_MAT_DIFF 1

View File

@@ -2246,6 +2246,7 @@ static void registerShaderNodes(bNodeTreeType *ttype)
register_node_type_sh_layer_weight(ttype); register_node_type_sh_layer_weight(ttype);
register_node_type_sh_tex_coord(ttype); register_node_type_sh_tex_coord(ttype);
register_node_type_sh_particle_info(ttype); register_node_type_sh_particle_info(ttype);
register_node_type_sh_bump(ttype);
register_node_type_sh_background(ttype); register_node_type_sh_background(ttype);
register_node_type_sh_bsdf_anisotropic(ttype); register_node_type_sh_bsdf_anisotropic(ttype);

View File

@@ -82,6 +82,7 @@ DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LI
DefNode( ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIGHT_FALLOFF", LightFalloff, "Light Falloff", "" ) DefNode( ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIGHT_FALLOFF", LightFalloff, "Light Falloff", "" )
DefNode( ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" ) DefNode( ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" )
DefNode( ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" ) DefNode( ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" )
DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", BumpNode, "Bump", "" )
DefNode( ShaderNode, SH_NODE_TEX_IMAGE, def_sh_tex_image, "TEX_IMAGE", TexImage, "Image Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_IMAGE, def_sh_tex_image, "TEX_IMAGE", TexImage, "Image Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_ENVIRONMENT, def_sh_tex_environment, "TEX_ENVIRONMENT", TexEnvironment, "Environment Texture","" ) DefNode( ShaderNode, SH_NODE_TEX_ENVIRONMENT, def_sh_tex_environment, "TEX_ENVIRONMENT", TexEnvironment, "Environment Texture","" )
DefNode( ShaderNode, SH_NODE_TEX_SKY, def_sh_tex_sky, "TEX_SKY", TexSky, "Sky Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_SKY, def_sh_tex_sky, "TEX_SKY", TexSky, "Sky Texture", "" )
@@ -92,7 +93,7 @@ DefNode( ShaderNode, SH_NODE_TEX_WAVE, def_sh_tex_wave, "TE
DefNode( ShaderNode, SH_NODE_TEX_MUSGRAVE, def_sh_tex_musgrave, "TEX_MUSGRAVE", TexMusgrave, "Musgrave Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_MUSGRAVE, def_sh_tex_musgrave, "TEX_MUSGRAVE", TexMusgrave, "Musgrave Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_VORONOI, def_sh_tex_voronoi, "TEX_VORONOI", TexVoronoi, "Voronoi Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_VORONOI, def_sh_tex_voronoi, "TEX_VORONOI", TexVoronoi, "Voronoi Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_CHECKER, def_sh_tex_checker, "TEX_CHECKER", TexChecker, "Checker Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_CHECKER, def_sh_tex_checker, "TEX_CHECKER", TexChecker, "Checker Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_BRICK, def_sh_tex_brick, "TEX_BRICK", TexBrick, "Brick Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_BRICK, def_sh_tex_brick, "TEX_BRICK", TexBrick, "Brick Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_COORD, def_sh_tex_coord, "TEX_COORD", TexCoord, "Texture Coordinate","" ) DefNode( ShaderNode, SH_NODE_TEX_COORD, def_sh_tex_coord, "TEX_COORD", TexCoord, "Texture Coordinate","" )
DefNode( CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" ) DefNode( CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" )

View File

@@ -153,6 +153,7 @@ set(SRC
shader/nodes/node_shader_bsdf_translucent.c shader/nodes/node_shader_bsdf_translucent.c
shader/nodes/node_shader_bsdf_transparent.c shader/nodes/node_shader_bsdf_transparent.c
shader/nodes/node_shader_bsdf_velvet.c shader/nodes/node_shader_bsdf_velvet.c
shader/nodes/node_shader_bump.c
shader/nodes/node_shader_emission.c shader/nodes/node_shader_emission.c
shader/nodes/node_shader_fresnel.c shader/nodes/node_shader_fresnel.c
shader/nodes/node_shader_layer_weight.c shader/nodes/node_shader_layer_weight.c

View File

@@ -110,6 +110,7 @@ void register_node_type_sh_tex_wave(struct bNodeTreeType *ttype);
void register_node_type_sh_tex_musgrave(struct bNodeTreeType *ttype); void register_node_type_sh_tex_musgrave(struct bNodeTreeType *ttype);
void register_node_type_sh_tex_noise(struct bNodeTreeType *ttype); void register_node_type_sh_tex_noise(struct bNodeTreeType *ttype);
void register_node_type_sh_tex_checker(struct bNodeTreeType *ttype); void register_node_type_sh_tex_checker(struct bNodeTreeType *ttype);
void register_node_type_sh_bump(struct bNodeTreeType *ttype);
#endif #endif

View File

@@ -33,6 +33,7 @@ static bNodeSocketTemplate sh_node_bsdf_anisotropic_in[]= {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Roughness U"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Roughness U"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Roughness V"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Roughness V"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" } { -1, 0, "" }
}; };

View File

@@ -32,6 +32,7 @@
static bNodeSocketTemplate sh_node_bsdf_diffuse_in[]= { static bNodeSocketTemplate sh_node_bsdf_diffuse_in[]= {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" } { -1, 0, "" }
}; };

View File

@@ -33,6 +33,7 @@ static bNodeSocketTemplate sh_node_bsdf_glass_in[]= {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 1.0f, 1000.0f}, { SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 1.0f, 1000.0f},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" } { -1, 0, "" }
}; };

View File

@@ -32,6 +32,7 @@
static bNodeSocketTemplate sh_node_bsdf_glossy_in[]= { static bNodeSocketTemplate sh_node_bsdf_glossy_in[]= {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Roughness"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Roughness"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" } { -1, 0, "" }
}; };

View File

@@ -31,6 +31,7 @@
static bNodeSocketTemplate sh_node_bsdf_translucent_in[]= { static bNodeSocketTemplate sh_node_bsdf_translucent_in[]= {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" } { -1, 0, "" }
}; };

View File

@@ -32,6 +32,7 @@
static bNodeSocketTemplate sh_node_bsdf_velvet_in[]= { static bNodeSocketTemplate sh_node_bsdf_velvet_in[]= {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Sigma"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Sigma"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" } { -1, 0, "" }
}; };

View File

@@ -0,0 +1,63 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2005 Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/nodes/shader/nodes/node_shader_bump.c
* \ingroup shdnodes
*/
#include "node_shader_util.h"
/* **************** BUMP ******************** */
static bNodeSocketTemplate sh_node_bump_in[]= {
{ SOCK_FLOAT, 1, "Strength", 0.1f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{ SOCK_FLOAT, 1, "Height", 1.0f, 1.0f, 1.0f, 1.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" }
};
static bNodeSocketTemplate sh_node_bump_out[]= {
{ SOCK_VECTOR, 0, "Normal"},
{ -1, 0, "" }
};
/* node type definition */
void register_node_type_sh_bump(bNodeTreeType *ttype)
{
static bNodeType ntype;
node_type_base(ttype, &ntype, SH_NODE_BUMP, "Bump", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bump_in, sh_node_bump_out);
node_type_size(&ntype, 150, 60, 200);
node_type_storage(&ntype, "BumpNode", node_free_standard_storage, node_copy_standard_storage);
node_type_exec(&ntype, NULL);
nodeRegisterType(ttype, &ntype);
}