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));
}
Example #11
0
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);
}
Example #13
0
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;
}
Example #17
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;
}
Example #20
0
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;
}