diff options
5 files changed, 57 insertions, 25 deletions
diff --git a/source/blender/nodes/shader/nodes/node_shader_fresnel.c b/source/blender/nodes/shader/nodes/node_shader_fresnel.c index 917a06b3536..d5e11795fc0 100644 --- a/source/blender/nodes/shader/nodes/node_shader_fresnel.c +++ b/source/blender/nodes/shader/nodes/node_shader_fresnel.c @@ -51,27 +51,6 @@ static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *UNUSED(node), bNodeE return GPU_stack_link(mat, "node_fresnel", in, out, GPU_builtin(GPU_VIEW_POSITION)); } -static float fresnel_dielectric(float incoming[3], float normal[3], float eta) -{ - /* compute fresnel reflectance without explicitly computing - * the refracted direction */ - float c = fabs(dot_v3v3(incoming, normal)); - float g = eta * eta - 1.0 + c * c; - float result; - - if (g > 0.0) { - g = sqrtf(g); - float A = (g - c) / (g + c); - float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0); - result = 0.5 * A * A * (1.0 + B * B); - } - else { - result = 1.0; /* TIR (no refracted component) */ - } - - return result; -} - static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) { ShadeInput *shi = ((ShaderCallData *)data)->shi; @@ -88,7 +67,7 @@ static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *UNUS if(shi->use_world_space_shading) mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), n); - out[0]->vec[0] = fresnel_dielectric(shi->view, n, shi->flippednor ? 1/eta : eta); + out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, shi->flippednor ? 1/eta : eta); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c index 8cbc587e339..90e2625b961 100644 --- a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c +++ b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c @@ -45,23 +45,53 @@ static int node_shader_gpu_layer_weight(GPUMaterial *mat, bNode *UNUSED(node), b { if (!in[1].link) in[1].link = GPU_builtin(GPU_VIEW_NORMAL); - else + else if (GPU_material_use_world_space_shading(mat)) { GPU_link(mat, "direction_transform_m4v3", in[1].link, GPU_builtin(GPU_VIEW_MATRIX), &in[1].link); + } return GPU_stack_link(mat, "node_layer_weight", in, out, GPU_builtin(GPU_VIEW_POSITION)); } +static void node_shader_exec_layer_weight(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) +{ + ShadeInput *shi = ((ShaderCallData *)data)->shi; + float blend = in[0]->vec[0]; + float eta = max_ff(1 - blend, 0.00001); + + float n[3]; + if (in[1]->hasinput) { + copy_v3_v3(n, in[1]->vec); + } + else { + copy_v3_v3(n, shi->vn); + } + + if (shi->use_world_space_shading) + mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), n); + + out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, shi->flippednor ? eta : 1/eta); + + float facing = fabs(dot_v3v3(shi->view, n)); + if (blend != 0.5) { + CLAMP(blend, 0.0, 0.99999); + blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend); + facing = pow(facing, blend); + } + out[1]->vec[0] = 1.0 - facing; +} + /* node type definition */ void register_node_type_sh_layer_weight(void) { static bNodeType ntype; sh_node_type_base(&ntype, SH_NODE_LAYER_WEIGHT, "Layer Weight", NODE_CLASS_INPUT, 0); - node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_compatibility(&ntype, NODE_NEW_SHADING | NODE_OLD_SHADING); node_type_socket_templates(&ntype, sh_node_layer_weight_in, sh_node_layer_weight_out); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); node_type_gpu(&ntype, node_shader_gpu_layer_weight); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_layer_weight); nodeRegisterType(&ntype); } diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 73867de6b2e..ae389fdfd2e 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -218,6 +218,8 @@ int multitex_nodes(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]); void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]); +float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta); + /* shaded view and bake */ struct Render; struct Image; diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h index 27867eadbb4..13f16ce0bd7 100644 --- a/source/blender/render/intern/include/shading.h +++ b/source/blender/render/intern/include/shading.h @@ -99,7 +99,7 @@ ListBase *get_lights(struct ShadeInput *shi); float lamp_get_visibility(struct LampRen *lar, const float co[3], float lv[3], float *dist); void lamp_get_shadow(struct LampRen *lar, ShadeInput *shi, float inp, float shadfac[4], int do_real); -float fresnel_fac(const float view[3], const float vn[3], float fresnel, float fac); +float fresnel_fac(const float view[3], const float vn[3], float fresnel, float fac); /* rayshade.c */ extern void shade_ray(struct Isect *is, struct ShadeInput *shi, struct ShadeResult *shr); diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 3d6462e09a0..c4de95e863e 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -2151,3 +2151,24 @@ const float (*RE_render_current_get_matrix(int matrix_id))[4] } return NULL; } + +float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) +{ + /* compute fresnel reflectance without explicitly computing + * the refracted direction */ + float c = fabs(dot_v3v3(incoming, normal)); + float g = eta * eta - 1.0 + c * c; + float result; + + if (g > 0.0) { + g = sqrtf(g); + float A = (g - c) / (g + c); + float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0); + result = 0.5 * A * A * (1.0 + B * B); + } + else { + result = 1.0; /* TIR (no refracted component) */ + } + + return result; +}
\ No newline at end of file |