Jump to content
Alanw

custom VEX COP issues

Recommended Posts

My goal for this weekend was to implement some blending modes from Gimp/Photoshop into COP's and learn a little VEX as well. I've got them working in RSL shaders previously, but I'm having trouble now. (All functions are credit to Jens Gruschel's work http://www.pegtop.net/delphi/articles/blendmodes/ )

I've only implemented Soft Light for now until I get everything working. My first problem is the COP node shows 1 input less then it should no matter how many I tell it to display. ie. #pragma opmaxinputs 2 gives me 1 input... 4 gives me 3. Ideally I want 2 working inputs.

Also, is there any main differences between RSL and VEX expressions? I've read up as much as I could find, and it seems like everything is the same as RSL as far as using parenthesis and which operators get precedence, but I can't get this code below to work. VCC is telling me "a value of type "void" cannot be assigned".

return lerp(basemap, ctemp + (basemap * (1-((1-basemap) * (1-layer)) - ctemp)), opac);

I've worked around this by separating everything into small chunks of code, and it's working. I would like to understand why the above code isn't working though.

Here is what I've got for SoftLight.

 #pragma opmininputs 1
 #pragma opmaxinputs 4
 #pragma label opac opac
 #pragma range opac 0 1

 cop2 
 blendingModes(float opac = 0.5 )
 {


	vector4 c1;
	vector4 c2;
	vector4 ctemp;
	vector4 sub1 = 1;
	vector4 sub2 = 1;
	vector4 blend;
	vector4 product;
	vector4 sum;

	float r1;
	float g1;
	float b1;
	float a1;

	c1 = cinput(0,PL,IX,IY);
	c2 = cinput(1,PL,IX,IY);
	//c2 = finput(1,PL,AI,0,IX,IY,0);

	ctemp = c1 * c2;
	sub1 = c1 - 1;
	sub2 = c2 - 1;	
	product = sub1 * sub2;
	product -= 1;
	product = (ctemp - product) * c1;	
	sum = product + ctemp;

	blend = lerp(c1, sum, opac);

	assign(r1, g1, b1, a1, blend);

	float r2 = r1;
	float g2 = g1;
	float b2 = b1;
	float a2 = a1;

	R = r2;
	G = g2;
	B = b2;
	A = a2;


 }

Thanks,

Alan

Share this post


Link to post
Share on other sites

The reason you're getting the error is because '1' is an integer, and VEX is very type-explicit. It appears that while vector4 - int is supported, int - vector4 isn't. Probably the easiest solution is just to create a vector4 with 1 in it:

vector4 one;
one = set(1.0, 1.0, 1.0, 1.0);
....
blend = lerp(c1, ctemp + (c1*one - ((one - c1)*(one - c2)) - ctemp), opac);

VEX filters always have a mask input; this is where your missing input is going. Bump your maximum inputs by 1 and you'll get what you expect.

Share this post


Link to post
Share on other sites

Sorry, another question. How would I go about comparing vector data to one another?

for example.

if(c1 < c2) throws the same error.

At first, I thought maybe this was due to the alpha channel being present in vector4 types, but extracting the RGB and comparing normal vectors throws the same error.

The Darken blending mode looks for areas of the pixels that have lower value (0 to 1 in RGB) and assigns which image to display accordingly.

I could average the RGB components, but I'm not sure this has the same effect? It does indeed compile and looks okay... I'm not sure it's the same though.

	if(mode == "Darken")
	{

		if((c1.r + c1.g + c1.b)/3 &lt; (c2.r + c2.g + c2.b)/3)
		{
			blend = c1;
		} else {
			blend = c2;
		}
	}

Edited by Alanw

Share this post


Link to post
Share on other sites

I could be wrong but most of these blending modes operates on RGB channel separetly, so what you'd like to do is to proceed every color one by one.

Share this post


Link to post
Share on other sites

Yes, most photoshop effects work on the RGB channel independently.

Share this post


Link to post
Share on other sites

Some of them require me to separate the channels, but I could get away with not doing it in a few cases like SoftLight.

Not all of my implementations are correct though, but it was a fun learning experience, and I will probably use a lot of these in my work.

Here's the code if anyone wants to use them. They work pretty well.

Thanks for the help.

/*cop_blendingModes.vfl - implementation of additional blending modes for COPS.
 *
 * written by Alan Warren
 *
 * bluemoonshine@gmail.com
 * 
 * parameters:
 *	opac			blending opacity
 *	mode			blending mode
 *
 * credit:			All functions credit to Jens Gruschel - http://www.pegtop.net/delphi/articles/blendmodes
 *				with help from "The Renderman Shading Language Guide" Rudy Cortes &amp; Saty Raghavachary
 */


#pragma opmininputs 1
#pragma opmaxinputs 3

#pragma label opac opac
#pragma range opac 0 1

#pragma export mode all
#pragma choice mode "Over" "Over"
#pragma choice mode "Add" "Add"
#pragma choice mode "Subtract" "Subtract"
#pragma choice mode "Multiply" "Multiply"
#pragma choice mode "Overlay" "Overlay"
#pragma choice mode "Dodge" "Dodge"
#pragma choice mode "Burn" "Burn"
#pragma choice mode "Screen" "Screen"
#pragma choice mode "Darken" "Darken"
#pragma choice mode "Lighten" "Lighten"
#pragma choice mode "Difference" "Difference"
#pragma choice mode "HardLight" "HardLight"
#pragma choice mode "SoftLight"	"SoftLight"


cop2
blendingModes(string mode = "Over";
		  float opac = 0.5)
{


	vector4 c1;
	vector4 c2;
	vector4 ctemp;
	vector4 one;
	vector4 two;
	vector4 blend;
	vector4 glowVec;

	float c1_to_float;
	float c2_to_float;
	float mixer;
	float smoother = 0.2;

	float r1;
	float g1;
	float b1;
	float a1;

	c1 = cinput(0,PL,IX,IY);
	c2 = cinput(1,PL,IX,IY);
	//c2 = finput(1,PL,AI,0,IX,IY,0);
	// todo: give user choice to use filtered version

	ctemp = c1 * c2;
	one = set(1.0, 1.0, 1.0, 1.0);
	two = set(2.0, 2.0, 2.0, 2.0);
	c1_to_float = (c1.r + c1.b + c1.b)/3;
	c2_to_float = (c2.r + c2.b + c2.b)/3;

	if(mode == "Over")
	{
		blend = lerp(c1, c2, opac);
	}

	if(mode == "Add")
	{
		blend = c1 + (c2 * opac);
	}

	if(mode == "Subtract")
	{
		blend = c1 + ((c2-one) * opac);
	}

	if(mode == "Multiply")
	{
		blend = c1 * ((c2 * opac) + (one - opac));
	}


	if(mode == "Overlay")
	{
	// my own implementation, so it's close but not accurate  
	ctemp.r =  lerp(c2_to_float * (2 * c1.r * c2.r * opac) + c1.r * (1 - opac), c2_to_float + 1 - ((1-c1.r) * (1 - c1.r * opac)) * (2 - (1 - opac)), opac);
	ctemp.g =  lerp(c2_to_float * (2 * c1.g * c2.g * opac) + c1.g * (1 - opac), c2_to_float + 1 - ((1-c1.g) * (1 - c1.g * opac)) * (2 - (1 - opac)), opac);
	ctemp.b =  lerp(c2_to_float * (2 * c1.b * c2.b * opac) + c1.b * (1 - opac), c2_to_float + 1 - ((1-c1.b) * (1 - c1.b * opac)) * (2 - (1 - opac)), opac);
	ctemp.a =  c1.a;
	blend = clamp(ctemp, {0,0,0,0}, {1,1,1,1});
	}

	if(mode == "Dodge")
	{
		//_to_float
		ctemp.r = lerp(c1.r, c1.r / max(1 - c2.r, 0.0001), opac);
		ctemp.g = lerp(c1.g, c1.g / max(1 - c2.g, 0.0001), opac);
		ctemp.b = lerp(c1.b, c1.b / max(1 - c2.b, 0.0001), opac);
		ctemp.a = lerp(c1.a, c1.a / max(1 - c2.a, 0.0001), opac);
		blend = clamp(ctemp, {0,0,0,0}, {1,1,1,1});
	}

	if(mode == "Burn")
	{
		ctemp.r = lerp(c1.r, 1-((1-c1.r) / max(c2.r, 0.0001)), opac);
		ctemp.g = lerp(c1.g, 1-((1-c1.g) / max(c2.g, 0.0001)), opac);
		ctemp.b = lerp(c1.b, 1-((1-c1.b) / max(c2.b, 0.0001)), opac);
		ctemp.a = lerp(c1.a, 1-((1-c1.a) / max(c2.a, 0.0001)), opac);
		blend = clamp(ctemp, {0,0,0,0}, {1,1,1,1});
	}

	if(mode == "Screen")
	{
		blend = one - (one - c1) * (one - c2);
	}

	if(mode == "Darken")
	{
		mixer = 1 - smooth(c1_to_float - smoother, c1_to_float + smoother, c2_to_float);

		blend = lerp(c1, c2, mixer);
	}

	if(mode == "Lighten")
	{
		mixer = smooth(c1_to_float - smoother, c1_to_float + smoother, c2_to_float);

		blend = lerp(c1, c2, mixer);
	}

	if(mode == "Difference")
	{
		blend = abs(c1 - c2); 
	}

	if(mode == "HardLight")
	{		
	//not accurate
	ctemp.r =  lerp((c2_to_float * 2 * c1.r * c2.r * opac) + c1.r * (1 - opac), c2_to_float * (2 * c1.r * c2.r * opac) + c1.r * (1 - opac), opac) +
	lerp(c1_to_float + 1 - ((1-c1.r) * (1 - c2.r * opac)) * (2 - (1-opac)), c2_to_float + 1 - ((1-c1.r) * (1 - c2.r * opac)) * (2 - (1-opac)),opac);
	ctemp.g =  lerp((c2_to_float * 2 * c1.g * c2.g * opac) + c1.g * (1 - opac), c2_to_float * (2 * c1.g * c2.g * opac) + c1.g * (1 - opac), opac) +
	lerp(c1_to_float + 1 - ((1-c1.g) * (1 - c2.g * opac)) * (2 - (1-opac)), c2_to_float + 1 - ((1-c1.g) * (1 - c2.g * opac)) * (2 - (1-opac)),opac);
	ctemp.b =  lerp((c2_to_float * 2 * c1.b * c2.b * opac) + c1.b * (1 - opac), c2_to_float * (2 * c1.b * c2.b * opac) + c1.b * (1 - opac), opac) +
	lerp(c1_to_float + 1 - ((1-c1.b) * (1 - c2.b * opac)) * (2 - (1-opac)), c2_to_float + 1 - ((1-c1.b) * (1 - c2.b * opac)) * (2 - (1-opac)),opac);

	ctemp.a =  c1.a;
	blend = clamp(ctemp, {0,0,0,0}, {1,1,1,1});

	}

	if(mode == "SoftLight")
	{
		blend = lerp(c1, ctemp+(c1*(one - ((one - c1)*(one - c2)) - ctemp)), opac);
	}



	assign(r1, g1, b1, a1, blend);

	float r2 = r1;
	float g2 = g1;
	float b2 = b1;
	float a2 = a1;

	R = r2;
	G = g2;
	B = b2;
	A = a2;


}

Edited by Alanw

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×