OSL – Merge2

Merge two inputs using Nuke-style operations.

merge2_rndr1

Download link
http://www.rensheeren.com/osl/merge2_tex_v001.osl

Features
– Merge two inputs.

How to use
VRay:
– Create a VRay OSL Texture map.
– Load in the download OSL shader.
– Input two maps and select a mode.
– Alpha channels are taken into account.

merge2_node

merge2_ui

Properties
input_A
– The A input.
input_B
– The B input.
mode
– The merge operation.

Modes:
1 atop
2 average
3 difference
4 divide
5 from
6 geometric
7 hardlight
8 hypot
9 in
10 mask
11 matte
12 max
13 min
14 minus
15 multiply
16 out
17 over
18 overlay
19 plus
20 screen
21 stencil
22 under
23 xor

See also this link for an example of the merge modes.

/* 

merge2_tex_v001


By Rens Heeren (mail [at] rensheeren [dot] com)


Use as an OSL texture, not as an OSL material.


Merge two inputs using Nuke-type operations.

Modes:

1  atop
2  average
3  difference
4  divide
5  from
6  geometric
7  hardlight
8  hypot
9  in
10 mask
11 matte
12 max
13 min
14 minus
15 multiply
16 out
17 over
18 overlay
19 plus
20 screen
21 stencil
22 under
23 xor 


Use at your own risk.


2016/01/05 - Created (rh)

*/

float fn_screen(float f_sA, float f_sB)
{
	float f_return = 0;
	if (f_sA >= 0 && f_sA <= 1 && f_sB >= 0 && f_sB <= 1)
	{
		f_return = f_sA + f_sB - f_sA * f_sB;
	}
	else 
	{
		if (f_sA >  f_sB)
		{
			f_return = f_sA;
		}
		else
		{
			f_return = f_sB;
		}
	}
	return f_return;
}

float fn_hardlight(float f_sA, float f_sB)
{
	float f_return = 0;
	if (f_sA < 0.5)
	{
		f_return = f_sA * f_sB;
	}
	else
	{
		f_return = fn_screen(f_sA, f_sB);
	}
	
	return f_return;
}

shader
merge2_tex_v001
(
#ifdef __VRAY_OSL__
	string input_A = ""
		[[ string description = "Input A" ]],
	string input_B = ""
		[[ string description = "Input B" ]],
#else
	color input_A = color(0)
		[[ string description = "Input A" ]],
	color input_B = color(0)
		[[ string description = "Input B" ]],
	float alpha_A = 0,
	float alpha_B = 0,
	
#endif
	
	
	int mode = 1
		[[ string widget = "mapper",
        string description = "1 atop, 2 average, 3 difference, 4 divide, 5 from, 6 geometric, 7 hardlight, 8 hypot, 9 in, 10 mask, 11 matte, 12 max, 13 min, 14 minus, 15 multiply, 16 out, 17 over, 18 overlay, 19 plus, 20 screen, 21 stencil, 22 under, 23 xor",
		string options = "1 atop:1|2 average:2|3 difference:3|4 divide:4|5 from:5|6 geometric:6|7 hardlight:7|8 hypot:8|9 in:9|10 mask:10|11 matte:11|12 max:12|13 min:13|14 minus:14|15 multiply:15|16 out:16|17 over:17|18 overlay:18|19 plus:19|20 screen:20|21 stencil:21|22 under:22|23 xor:23"]],

#ifdef __VRAY_OSL__
	string mode_tex = "",
	int use_mode_tex = 0
		[[ string widget = "checkBox" ]],
#endif

	string website = "www.rensheeren.com/blog/osl-merge2/"
	  [[ string widget = "string" ]],


	output color out_col = color(0),
	
	output float out_alpha = 0,
	output float out_white = 1

)

///////////////////////////////////////////

{
	int i_mode = mode;
	float f_A = 0;
	float f_B = 0;
#ifdef __VRAY_OSL__
	color c_A = texture(input_A, u, v, "alpha", f_A);
	color c_B = texture(input_B, u, v, "alpha", f_B);
	
	int i_useModeTex = use_mode_tex;


	if (i_useModeTex)
	{
		color c_modeTex = texture(mode_tex, u , v);
		i_mode = (int)floor(c_modeTex[0]);
	}
#else
	color c_A = input_A;
	color c_B = input_B;
	f_A = alpha_A;
	f_B = alpha_B;
#endif
	color c_out = color(0);
	float f_out = 0;
	
	
	
	// atop
	if (i_mode == 1)
	{
		c_out = (c_A *  f_B) + (c_B * (1.0 - f_A));
		f_out = (f_A *  f_B) + (f_B * (1.0 - f_A));
	}
	
	// average
	if (i_mode == 2)
	{
		c_out = (c_A + c_B) / 2;
		f_out = (f_A + f_B) / 2;
	}
	
	// difference
	if (i_mode == 3)
	{
		c_out = abs(c_A - c_B);
		f_out = abs(f_A - f_B);
	}
	
	// divide
	if (i_mode == 4)
	{
		c_out = c_A / c_B;
		f_out = f_A / f_B;
	}
	
	// from
	if (i_mode == 5)
	{
		c_out = c_B - c_A;
		f_out = f_B - f_A;
	}
	
	// geometric
	if (i_mode == 6)
	{
		c_out = (2 * c_A * c_B) / (c_A + c_B);
		f_out = (2 * f_A * f_B) / (f_A + f_B);
	}
	
	// hardlight
	if (i_mode == 7)
	{
		c_out[0] = fn_hardlight(c_A[0], c_B[0]);
		c_out[1] = fn_hardlight(c_A[1], c_B[1]);
		c_out[2] = fn_hardlight(c_A[2], c_B[2]);
		f_out = fn_hardlight(f_A, f_B);
	}
	
	// hypot
	if (i_mode == 8)
	{
		c_out = sqrt(c_A * c_A + c_B * c_B);
		f_out = sqrt(f_A * f_A + f_B * f_B);
	}
	
	// in
	if (i_mode == 9)
	{
		c_out = c_A * f_B;
		f_out = f_A * f_B;
	}
	
	// mask
	if (i_mode == 10)
	{
		c_out = c_B * f_A;
		f_out = f_B * f_A;
	}
	
	// matte
	if (i_mode == 11)
	{
		c_out = c_A * f_A + c_B * (1 - f_A);
		f_out = f_A * f_A + f_B * (1 - f_A);
	}
	
	// max
	if (i_mode == 12)
	{
		c_out = max(c_A, c_B);
		f_out = max(f_A, f_B);
	}
	
	// min
	if (i_mode == 13)
	{
		c_out = min(c_A, c_B);
		f_out = min(f_A, f_B);
	}
	
	// minus
	if (i_mode == 14)
	{
		c_out = c_A - c_B;
		f_out = f_A - f_B;
	}
	
	// multiply
	if (i_mode == 15)
	{
		c_out = c_A * c_B;
		f_out = f_A * f_B;
	}
	
	// out
	if (i_mode == 16)
	{
		c_out = c_A * (1 - f_B);
		f_out = f_A * (1 - f_B);
	}
	
	// over
	if (i_mode == 17)
	{
		c_out = c_A + c_B * (1 - f_A);
		f_out = f_A + f_B * (1 - f_A);
	}
	
	// overlay
	if (i_mode == 18)
	{
		c_out = c_A + c_B * (1 - f_A);
		f_out = f_A + f_B * (1 - f_A);
	}
	
	// plus
	if (i_mode == 19)
	{
		c_out = c_A + c_B * (1 - f_A);
		f_out = f_A + f_B * (1 - f_A);
	}
	
	// screen
	if (i_mode == 20)
	{
		
		c_out[0] = fn_screen(c_A[0], c_B[0]);
		c_out[1] = fn_screen(c_A[1], c_B[1]);
		c_out[2] = fn_screen(c_A[2], c_B[2]);
		f_out = fn_screen(f_A, f_B);
	}

	// stencil
	if (i_mode == 21)
	{
		c_out = c_B * (1 - f_A);
		f_out = f_B * (1 - f_A);
	}	
	
	// under
	if (i_mode == 22)
	{
		c_out = c_A * (1 - f_B) + c_B;
		f_out = f_A * (1 - f_B) + f_B;
	}
	
	// xor
	if (i_mode == 23)
	{
		c_out = c_A * (1 - f_B) + c_B * (1 - f_A);
		f_out = f_A * (1 - f_B) + f_B * (1 - f_A);
	}
	
	
	out_col = c_out;
	out_alpha = f_out;
	
	// + PS modes
	
}