static void node_shader_gpu_volume_attribute(GPUMaterial *mat, const char *name, GPUNodeLink **outcol, GPUNodeLink **outvec, GPUNodeLink **outf) { if (strcmp(name, "density") == 0) { GPU_link(mat, "node_attribute_volume_density", GPU_builtin(GPU_VOLUME_DENSITY), outcol, outvec, outf); } else if (strcmp(name, "color") == 0) { GPU_link( mat, "node_attribute_volume_color", GPU_builtin(GPU_VOLUME_DENSITY), outcol, outvec, outf); } else if (strcmp(name, "flame") == 0) { GPU_link( mat, "node_attribute_volume_flame", GPU_builtin(GPU_VOLUME_FLAME), outcol, outvec, outf); } else if (strcmp(name, "temperature") == 0) { GPU_link(mat, "node_attribute_volume_temperature", GPU_builtin(GPU_VOLUME_FLAME), GPU_builtin(GPU_VOLUME_TEMPERATURE), outcol, outvec, outf); } else { *outcol = *outvec = *outf = NULL; } }
static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { Image *ima = (Image *)node->id; ImageUser *iuser = NULL; NodeTexImage *tex = node->storage; GPUNodeLink *norm; int isdata = tex->color_space == SHD_COLORSPACE_NONE; float blend = tex->projection_blend; if (!ima) return GPU_stack_link(mat, "node_tex_image_empty", in, out); if (!in[0].link) in[0].link = GPU_attribute(CD_MTFACE, ""); node_shader_gpu_tex_mapping(mat, node, in, out); switch (tex->projection) { case SHD_PROJ_FLAT: GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata)); break; case SHD_PROJ_BOX: GPU_link(mat, "direction_transform_m4v3", GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &norm); GPU_link(mat, "direction_transform_m4v3", norm, GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), &norm); GPU_link(mat, "node_tex_image_box", in[0].link, norm, GPU_image(ima, iuser, isdata), GPU_uniform(&blend), &out[0].link, &out[1].link); break; case SHD_PROJ_SPHERE: GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link); GPU_link(mat, "point_map_to_sphere", in[0].link, &in[0].link); GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata)); break; case SHD_PROJ_TUBE: GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link); GPU_link(mat, "point_map_to_tube", in[0].link, &in[0].link); GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata)); break; } ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if ((tex->color_space == SHD_COLORSPACE_COLOR) && ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); } BKE_image_release_ibuf(ima, ibuf, NULL); return true; }
static int node_shader_gpu_oct_tex_float_image(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { int ret; float rgb[4]; int isdata; Image *ima = (Image*)node->id; ImageUser *iuser = NULL; NodeTexImage *tex = node->storage; if(!tex) { node_oct_float_image_tex_init(0, node); tex = node->storage; } isdata = tex->color_space == SHD_COLORSPACE_NONE; in[0].type = GPU_VEC3; in[0].link = GPU_attribute(CD_MTFACE, ""); in[1].type = GPU_NONE; if(!ima) return GPU_stack_link(mat, "node_tex_image_empty", in, out, GPU_uniform(rgb)); node_shader_gpu_tex_mapping(mat, node, in, out); ret = GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata), GPU_uniform(rgb)); if(ret) { ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); } BKE_image_release_ibuf(ima, ibuf, NULL); } return ret; }
static int gpu_shader_bump(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[3].link) in[3].link = GPU_builtin(GPU_VIEW_NORMAL); else GPU_link(mat, "direction_transform_m4v3", in[3].link, GPU_builtin(GPU_VIEW_MATRIX), &in[3].link); float invert = node->custom1; GPU_stack_link(mat, "node_bump", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_uniform(&invert)); /* Other nodes are applying view matrix if the input Normal has a link. * We don't want normal to have view matrix applied twice, so we cancel it here. * * TODO(sergey): This is an extra multiplication which cancels each other, * better avoid this but that requires bigger refactor. */ return GPU_link(mat, "direction_transform_m4v3", out[0].link, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &out[0].link); }
static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) { Image *ima= (Image*)node->id; ImageUser *iuser= NULL; NodeTexImage *tex = node->storage; int isdata = tex->color_space == SHD_COLORSPACE_NONE; int ret; if (!ima) return GPU_stack_link(mat, "node_tex_environment_empty", in, out); if (!in[0].link) in[0].link = GPU_builtin(GPU_VIEW_POSITION); node_shader_gpu_tex_mapping(mat, node, in, out); ret = GPU_stack_link(mat, "node_tex_environment", in, out, GPU_image(ima, iuser, isdata)); if (ret) { ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); } BKE_image_release_ibuf(ima, ibuf, NULL); } return ret; }
static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[5].link) in[5].link = GPU_builtin(GPU_VIEW_NORMAL); else GPU_link(mat, "direction_transform_m4v3", in[5].link, GPU_builtin(GPU_VIEW_MATRIX), &in[5].link); return GPU_stack_link(mat, "node_subsurface_scattering", in, out); }
static int node_shader_gpu_layer_weight(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[1].link) in[1].link = GPU_builtin(GPU_VIEW_NORMAL); 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)); }
void node_shader_gpu_tex_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *UNUSED(out)) { NodeTexBase *base = node->storage; TexMapping *texmap = &base->tex_mapping; float domin = (texmap->flag & TEXMAP_CLIP_MIN) != 0; float domax = (texmap->flag & TEXMAP_CLIP_MAX) != 0; if (domin || domax || !(texmap->flag & TEXMAP_UNIT_MATRIX)) { GPUNodeLink *tmat = GPU_uniform((float *)texmap->mat); GPUNodeLink *tmin = GPU_uniform(texmap->min); GPUNodeLink *tmax = GPU_uniform(texmap->max); GPUNodeLink *tdomin = GPU_uniform(&domin); GPUNodeLink *tdomax = GPU_uniform(&domax); GPU_link(mat, "mapping", in[0].link, tmat, tmin, tmax, tdomin, tdomax, &in[0].link); if (texmap->type == TEXMAP_TYPE_NORMAL) GPU_link(mat, "texco_norm", in[0].link, &in[0].link); } }
static int node_shader_gpu_tex_checker(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[0].link) { in[0].link = GPU_attribute(CD_ORCO, ""); GPU_link(mat, "generated_from_orco", in[0].link, &in[0].link); } node_shader_gpu_tex_mapping(mat, node, in, out); return GPU_stack_link(mat, "node_tex_checker", in, out); }
static int node_shader_gpu_tex_gradient(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[0].link) { in[0].link = GPU_attribute(CD_ORCO, ""); GPU_link(mat, "generated_from_orco", in[0].link, &in[0].link); } node_shader_gpu_tex_mapping(mat, node, in, out); NodeTexGradient *tex = (NodeTexGradient *)node->storage; float gradient_type = tex->gradient_type; return GPU_stack_link(mat, "node_tex_gradient", in, out, GPU_uniform(&gradient_type)); }
static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[3].link) { GPU_link(mat, "world_normals_get", &in[3].link); } GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY | GPU_MATFLAG_REFRACT); return GPU_stack_link(mat, node, "node_bsdf_glass", in, out, GPU_constant(&node->ssr_id)); }
static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[2].link) { GPU_link(mat, "world_normals_get", &in[2].link); } GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE); return GPU_stack_link(mat, node, "node_ambient_occlusion", in, out); }
static int node_shader_gpu_tex_noise(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[0].link) { in[0].link = GPU_attribute(CD_ORCO, ""); GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), in[0].link, &in[0].link); } node_shader_gpu_tex_mapping(mat, node, in, out); return GPU_stack_link(mat, node, "node_tex_noise", in, out); }
static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { Image *ima = (Image *)node->id; ImageUser *iuser = NULL; NodeTexImage *tex = node->storage; int isdata = tex->color_space == SHD_COLORSPACE_NONE; if (!ima) return GPU_stack_link(mat, "node_tex_environment_empty", in, out); if (!in[0].link) { GPUMatType type = GPU_Material_get_type(mat); if (type == GPU_MATERIAL_TYPE_MESH) in[0].link = GPU_builtin(GPU_VIEW_POSITION); else GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &in[0].link); } node_shader_gpu_tex_mapping(mat, node, in, out); if (tex->projection == SHD_PROJ_EQUIRECTANGULAR) GPU_stack_link(mat, "node_tex_environment_equirectangular", in, out, GPU_image(ima, iuser, isdata)); else GPU_stack_link(mat, "node_tex_environment_mirror_ball", in, out, GPU_image(ima, iuser, isdata)); ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); } BKE_image_release_ibuf(ima, ibuf, NULL); return true; }
static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[0].link) { in[0].link = GPU_attribute(CD_ORCO, ""); GPU_link(mat, "generated_from_orco", in[0].link, &in[0].link); } node_shader_gpu_tex_mapping(mat, node, in, out); NodeTexBrick *tex = (NodeTexBrick *)node->storage; float offset_freq = tex->offset_freq; float squash_freq = tex->squash_freq; return GPU_stack_link(mat, "node_tex_brick", in, out, GPU_uniform(&tex->offset), GPU_uniform(&offset_freq), GPU_uniform(&tex->squash), GPU_uniform(&squash_freq)); }
static int gpu_shader_texture(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { Tex *tex = (Tex *)node->id; if (tex && tex->type == TEX_IMAGE && tex->ima) { GPUNodeLink *texlink = GPU_image(tex->ima, &tex->iuser, false); int ret = GPU_stack_link(mat, "texture_image", in, out, texlink); if (ret) { ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[1].link, &out[1].link); } BKE_image_release_ibuf(tex->ima, ibuf, NULL); } return ret; } else return 0; }
static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) { if(node->id) { GPUShadeInput shi; GPUShadeResult shr; GPU_shadeinput_set(mat, (Material*)node->id, &shi); /* write values */ if(in[MAT_IN_COLOR].hasinput) shi.rgb = in[MAT_IN_COLOR].link; if(in[MAT_IN_SPEC].hasinput) shi.specrgb = in[MAT_IN_SPEC].link; if(in[MAT_IN_REFL].hasinput) shi.refl = in[MAT_IN_REFL].link; /* retrieve normal */ if(in[MAT_IN_NORMAL].hasinput) { GPUNodeLink *tmp; shi.vn = in[MAT_IN_NORMAL].link; GPU_link(mat, "vec_math_normalize", shi.vn, &shi.vn, &tmp); } /* custom option to flip normal */ if(node->custom1 & SH_NODE_MAT_NEG) GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); if (node->type == SH_NODE_MATERIAL_EXT) { if(in[MAT_IN_AMB].hasinput) shi.amb= in[MAT_IN_AMB].link; if(in[MAT_IN_EMIT].hasinput) shi.emit= in[MAT_IN_EMIT].link; if(in[MAT_IN_ALPHA].hasinput) shi.alpha= in[MAT_IN_ALPHA].link; } GPU_shaderesult_set(&shi, &shr); /* clears shr */ /* write to outputs */ if(node->custom1 & SH_NODE_MAT_DIFF) { out[MAT_OUT_COLOR].link= shr.combined; if(!(node->custom1 & SH_NODE_MAT_SPEC)) { GPUNodeLink *link; GPU_link(mat, "vec_math_sub", shr.combined, shr.spec, &out[MAT_OUT_COLOR].link, &link); } } else if(node->custom1 & SH_NODE_MAT_SPEC) { out[MAT_OUT_COLOR].link= shr.spec; } else GPU_link(mat, "set_rgb_zero", &out[MAT_OUT_COLOR].link); GPU_link(mat, "mtex_alpha_to_col", out[MAT_OUT_COLOR].link, shr.alpha, &out[MAT_OUT_COLOR].link); out[MAT_OUT_ALPHA].link = shr.alpha; // if(node->custom1 & SH_NODE_MAT_NEG) GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); out[MAT_OUT_NORMAL].link = shi.vn; if (node->type == SH_NODE_MATERIAL_EXT) { out[MAT_OUT_DIFFUSE].link = shr.diff; out[MAT_OUT_SPEC].link = shr.spec; } return 1; } return 0; }
static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { Image *ima = (Image *)node->id; NodeTexEnvironment *tex = node->storage; /* We get the image user from the original node, since GPU image keeps * a pointer to it and the dependency refreshes the original. */ bNode *node_original = node->original ? node->original : node; NodeTexImage *tex_original = node_original->storage; ImageUser *iuser = &tex_original->iuser; GPUNodeLink *outalpha; if (!ima) { return GPU_stack_link(mat, node, "node_tex_environment_empty", in, out); } if (!in[0].link) { GPU_link(mat, "node_tex_environment_texco", GPU_builtin(GPU_VIEW_POSITION), &in[0].link); } node_shader_gpu_tex_mapping(mat, node, in, out); /* Compute texture coordinate. */ if (tex->projection == SHD_PROJ_EQUIRECTANGULAR) { /* To fix pole issue we clamp the v coordinate. The clamp value depends on the filter size. */ float clamp_size = (ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART)) ? 1.5 : 0.5; GPU_link(mat, "node_tex_environment_equirectangular", in[0].link, GPU_constant(&clamp_size), GPU_image(ima, iuser), &in[0].link); } else { GPU_link(mat, "node_tex_environment_mirror_ball", in[0].link, &in[0].link); } /* Sample texture with correct interpolation. */ switch (tex->interpolation) { case SHD_INTERP_LINEAR: /* Force the highest mipmap and don't do anisotropic filtering. * This is to fix the artifact caused by derivatives discontinuity. */ GPU_link(mat, "node_tex_image_linear_no_mip", in[0].link, GPU_image(ima, iuser), &out[0].link, &outalpha); break; case SHD_INTERP_CLOSEST: GPU_link(mat, "node_tex_image_nearest", in[0].link, GPU_image(ima, iuser), &out[0].link, &outalpha); break; default: GPU_link( mat, "node_tex_image_cubic", in[0].link, GPU_image(ima, iuser), &out[0].link, &outalpha); break; } if (out[0].hasoutput) { GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link); } return true; }
static int gpu_shader_normal_map(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { NodeShaderNormalMap *nm = node->storage; GPUNodeLink *negnorm; GPUNodeLink *realnorm; GPUNodeLink *strength; float d[4] = {0, 0, 0, 0}; if (in[0].link) strength = in[0].link; else strength = GPU_uniform(in[0].vec); if (in[1].link) realnorm = in[1].link; else realnorm = GPU_uniform(in[1].vec); negnorm = GPU_builtin(GPU_VIEW_NORMAL); GPU_link(mat, "math_max", strength, GPU_uniform(d), &strength); if (GPU_material_use_world_space_shading(mat)) { /* ******* CYCLES or BLENDER INTERNAL with world space shading flag ******* */ const char *color_to_normal_fnc_name = "color_to_normal_new_shading"; if (nm->space == SHD_SPACE_BLENDER_OBJECT || nm->space == SHD_SPACE_BLENDER_WORLD || !GPU_material_use_new_shading_nodes(mat)) color_to_normal_fnc_name = "color_to_blender_normal_new_shading"; switch (nm->space) { case SHD_SPACE_TANGENT: GPU_link(mat, "color_to_normal_new_shading", realnorm, &realnorm); GPU_link(mat, "node_normal_map", GPU_attribute(CD_TANGENT, nm->uv_map), negnorm, realnorm, &realnorm); GPU_link(mat, "vec_math_mix", strength, realnorm, GPU_builtin(GPU_VIEW_NORMAL), &out[0].link); /* for uniform scale this is sufficient to match Cycles */ GPU_link(mat, "direction_transform_m4v3", out[0].link, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &out[0].link); GPU_link(mat, "vect_normalize", out[0].link, &out[0].link); return true; case SHD_SPACE_OBJECT: case SHD_SPACE_BLENDER_OBJECT: GPU_link(mat, "direction_transform_m4v3", negnorm, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &negnorm); GPU_link(mat, color_to_normal_fnc_name, realnorm, &realnorm); GPU_link(mat, "direction_transform_m4v3", realnorm, GPU_builtin(GPU_OBJECT_MATRIX), &realnorm); break; case SHD_SPACE_WORLD: case SHD_SPACE_BLENDER_WORLD: GPU_link(mat, "direction_transform_m4v3", negnorm, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &negnorm); GPU_link(mat, color_to_normal_fnc_name, realnorm, &realnorm); break; } } else { /* ************** BLENDER INTERNAL without world space shading flag ******* */ GPU_link(mat, "color_to_normal", realnorm, &realnorm); GPU_link(mat, "mtex_negate_texnormal", realnorm, &realnorm); GPU_link(mat, "vec_math_negate", negnorm, &negnorm); switch (nm->space) { case SHD_SPACE_TANGENT: GPU_link(mat, "node_normal_map", GPU_attribute(CD_TANGENT, nm->uv_map), negnorm, realnorm, &realnorm); break; case SHD_SPACE_OBJECT: case SHD_SPACE_BLENDER_OBJECT: GPU_link(mat, "direction_transform_m4v3", realnorm, GPU_builtin(GPU_LOC_TO_VIEW_MATRIX), &realnorm); break; case SHD_SPACE_WORLD: case SHD_SPACE_BLENDER_WORLD: GPU_link(mat, "direction_transform_m4v3", realnorm, GPU_builtin(GPU_VIEW_MATRIX), &realnorm); break; } } GPU_link(mat, "vec_math_mix", strength, realnorm, negnorm, &out[0].link); GPU_link(mat, "vect_normalize", out[0].link, &out[0].link); return true; }
static int gpu_shader_material(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (node->id) { GPUShadeInput shi; GPUShadeResult shr; bNodeSocket *sock; char hasinput[NUM_MAT_IN] = {'\0'}; int i; /* note: cannot use the in[]->hasinput flags directly, as these are not necessarily * the constant input stack values (e.g. in case material node is inside a group). * we just want to know if a node input uses external data or the material setting. */ for (sock = node->inputs.first, i = 0; sock; sock = sock->next, ++i) hasinput[i] = (sock->link != NULL); GPU_shadeinput_set(mat, (Material *)node->id, &shi); /* write values */ if (hasinput[MAT_IN_COLOR]) shi.rgb = gpu_get_input_link(&in[MAT_IN_COLOR]); if (hasinput[MAT_IN_SPEC]) shi.specrgb = gpu_get_input_link(&in[MAT_IN_SPEC]); if (hasinput[MAT_IN_REFL]) shi.refl = gpu_get_input_link(&in[MAT_IN_REFL]); /* retrieve normal */ if (hasinput[MAT_IN_NORMAL]) { GPUNodeLink *tmp; shi.vn = gpu_get_input_link(&in[MAT_IN_NORMAL]); GPU_link(mat, "vec_math_normalize", shi.vn, &shi.vn, &tmp); } /* custom option to flip normal */ if (node->custom1 & SH_NODE_MAT_NEG) GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); if (node->type == SH_NODE_MATERIAL_EXT) { if (hasinput[MAT_IN_MIR]) shi.mir = gpu_get_input_link(&in[MAT_IN_MIR]); if (hasinput[MAT_IN_AMB]) shi.amb = gpu_get_input_link(&in[MAT_IN_AMB]); if (hasinput[MAT_IN_EMIT]) shi.emit = gpu_get_input_link(&in[MAT_IN_EMIT]); if (hasinput[MAT_IN_SPECTRA]) shi.spectra = gpu_get_input_link(&in[MAT_IN_SPECTRA]); if (hasinput[MAT_IN_ALPHA]) shi.alpha = gpu_get_input_link(&in[MAT_IN_ALPHA]); } GPU_shaderesult_set(&shi, &shr); /* clears shr */ /* write to outputs */ if (node->custom1 & SH_NODE_MAT_DIFF) { out[MAT_OUT_COLOR].link = shr.combined; if (!(node->custom1 & SH_NODE_MAT_SPEC)) { GPUNodeLink *link; GPU_link(mat, "vec_math_sub", shr.combined, shr.spec, &out[MAT_OUT_COLOR].link, &link); } } else if (node->custom1 & SH_NODE_MAT_SPEC) { out[MAT_OUT_COLOR].link = shr.spec; } else GPU_link(mat, "set_rgb_zero", &out[MAT_OUT_COLOR].link); GPU_link(mat, "mtex_alpha_to_col", out[MAT_OUT_COLOR].link, shr.alpha, &out[MAT_OUT_COLOR].link); out[MAT_OUT_ALPHA].link = shr.alpha; // if (node->custom1 & SH_NODE_MAT_NEG) GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); out[MAT_OUT_NORMAL].link = shi.vn; if (node->type == SH_NODE_MATERIAL_EXT) { out[MAT_OUT_DIFFUSE].link = shr.diff; out[MAT_OUT_SPEC].link = shr.spec; GPU_link(mat, "set_rgb_one", &out[MAT_OUT_AO].link); } return 1; } return 0; }