Alanw Posted June 30, 2008 Share Posted June 30, 2008 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 Quote Link to comment Share on other sites More sharing options...
malexander Posted June 30, 2008 Share Posted June 30, 2008 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. Quote Link to comment Share on other sites More sharing options...
Alanw Posted June 30, 2008 Author Share Posted June 30, 2008 Thanks! That makes perfect sense. Quote Link to comment Share on other sites More sharing options...
Alanw Posted June 30, 2008 Author Share Posted June 30, 2008 (edited) 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 < (c2.r + c2.g + c2.b)/3) { blend = c1; } else { blend = c2; } } Edited June 30, 2008 by Alanw Quote Link to comment Share on other sites More sharing options...
symek Posted June 30, 2008 Share Posted June 30, 2008 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. Quote Link to comment Share on other sites More sharing options...
edward Posted July 1, 2008 Share Posted July 1, 2008 Yes, most photoshop effects work on the RGB channel independently. Quote Link to comment Share on other sites More sharing options...
Alanw Posted July 1, 2008 Author Share Posted July 1, 2008 (edited) 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 & 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 July 1, 2008 by Alanw Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.