Layer Weight node support for Blender Internal Render
This commit is contained in:
parent
665110a414
commit
12e1732f72
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue