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;
}
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;
	float eta = max_ff(in[0]->vec[0], 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 ? 1/eta : eta);
}
static void node_shader_exec_normal_map(
        void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata),
        bNodeStack **in, bNodeStack **out)
{
	if (data) {
		ShadeInput *shi = ((ShaderCallData *)data)->shi;

		NodeShaderNormalMap *nm = node->storage;

		float strength, vecIn[3];
		nodestack_get_vec(&strength, SOCK_FLOAT, in[0]);
		nodestack_get_vec(vecIn, SOCK_VECTOR, in[1]);

		vecIn[0] = -2 * (vecIn[0] - 0.5f);
		vecIn[1] =  2 * (vecIn[1] - 0.5f);
		vecIn[2] =  2 * (vecIn[2] - 0.5f);

		CLAMP_MIN(strength, 0.0f);

		float *N = shi->nmapnorm;
		int uv_index = 0;
		switch (nm->space) {
			case SHD_SPACE_TANGENT:
				if (nm->uv_map[0]) {
					/* find uv map by name */
					for (int i = 0; i < shi->totuv; i++) {
						if (STREQ(shi->uv[i].name, nm->uv_map)) {
							uv_index = i;
							break;
						}
					}
				}
				else {
					uv_index = shi->actuv;
				}

				float *T = shi->tangents[uv_index];

				float B[3];
				cross_v3_v3v3(B, N, T);
				mul_v3_fl(B, T[3]);

				for (int j = 0; j < 3; j++)
					out[0]->vec[j] = vecIn[0] * T[j] + vecIn[1] * B[j] + vecIn[2] * N[j];
				interp_v3_v3v3(out[0]->vec, N, out[0]->vec, strength);
				if (shi->use_world_space_shading) {
					mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEWINV_MATRIX), out[0]->vec);
				}
				break;

			case SHD_SPACE_OBJECT:
			case SHD_SPACE_BLENDER_OBJECT:
				if (shi->use_world_space_shading) {
					mul_mat3_m4_v3((float (*)[4])RE_object_instance_get_matrix(shi->obi, RE_OBJECT_INSTANCE_MATRIX_OB), vecIn);
					mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEWINV_MATRIX), N);
				}
				else
					mul_mat3_m4_v3((float (*)[4])RE_object_instance_get_matrix(shi->obi, RE_OBJECT_INSTANCE_MATRIX_LOCALTOVIEW), vecIn);
				interp_v3_v3v3(out[0]->vec, N, vecIn, strength);
				break;

			case SHD_SPACE_WORLD:
			case SHD_SPACE_BLENDER_WORLD:
				if (shi->use_world_space_shading)
					mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEWINV_MATRIX), N);
				else
					mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), vecIn);
				interp_v3_v3v3(out[0]->vec, N, vecIn, strength);
				break;
		}
		if (shi->use_world_space_shading) {
			negate_v3(out[0]->vec);
		}
		normalize_v3(out[0]->vec);
	}
}