('aaaa', <_sre.SRE_Match object at 0x10391a750>) dst // pixel bender kernel name: omino_staragon_32 // languageVersion : 1.0 // category : "omino" // displayName : "omino staragon 32" // description : "draw or stroke regular polygons" // namespace : "omino" // version : 1 // vendor : "omino" uniform sampler2D src; // aeUIControl : "aeColor" // defaultValue : vec4(1,0,.3,1) // maxValue : vec4(1,1,1,1) // minValue : vec4(0,0,0,0) vec4 color1 = vec4(1,0,.3,1); // aeUIControl : "aeColor" // defaultValue : vec4(0,1,.3,1) // maxValue : vec4(1,1,1,1) // minValue : vec4(0,0,0,0) vec4 color2 = vec4(0,1,.3,1); // aeUIControl : "aePoint" // aePointRelativeDefaultValue : vec2(0.5,0.5) // defaultValue : vec2(220,220) vec2 center = vec2(220,220); // defaultValue : 5 // maxValue : 24 // minValue : 3 int sides = 5; // defaultValue : 0. // maxValue : 1. // minValue : 0. float pointiness = 0.; // defaultValue : 0 // maxValue : 2 // minValue : 0 // aeUIControl : "aePopup" // aePopupString : "color1|image|nothing" // aeDisplayValue : "drawn area" int drawn = 0; // defaultValue : 1 // maxValue : 2 // minValue : 0 // aeUIControl : "aePopup" // aePopupString : "color2|image|nothing" // aeDisplayValue : "undrawn area" int undrawn = 1; // defaultValue : 0 // maxValue : 1 // minValue : 0 // aeUIControl : "aePopup" // aePopupString : "fill|stroke" // aeDisplayValue : "style" int strokeOrFill = 0; // maxValue : 45.0 // defaultValue : 2.0 // aeDisplayValue : "stroke width" // minValue : 0.5 float strokeWidth = 2.0; // aeUIControl : "aeAngle" // parameterType : "angleDegrees" // defaultValue : 0.0 // maxValue : 360.0 // minValue : -360.0 float rotation = 0.0; // defaultValue : 90.0 // maxValue : 1000.0 // minValue : 0.0 float radius = 90.0; // maxValue : 1.0 // defaultValue : 0.05 // aeDisplayValue : "corner roundness" // minValue : 0.0 float roundness = 0.05; // maxValue : 1000.0 // defaultValue : 2.0 // aeDisplayValue : "edge blur" // minValue : 0.0 float edge = 2.0; // maxValue : 100.0 // defaultValue : 0.0 // aeDisplayValue : "ring count" // minValue : 0.0 float ringCount = 0.0; // maxValue : 100.0 // defaultValue : 5.0 // aeDisplayValue : "ring spacing" // minValue : 0.0 float ringSpacing = 5.0; /* * Two points lineStart and lineEnd define an infinite line. * Return the distance of point P from that line, where the * distance is positive if it's on the right (as you walk drom * lineStart to lineEnd) and negative on the left. */ float distanceFromLine(vec2 lineStart,vec2 lineEnd,vec2 p) { // and now, a bit of fun math, as we plot a line between two points. vec2 uv = p - lineStart; vec2 xy = lineEnd - lineStart; float xy2 = dot(xy,xy); float dl = -(dot(uv,vec2(-xy.y,xy.x)) / xy2 * length(xy)); // dl is now the distance, in pixels, from outCoord to the line return dl; } void main() { // Start with the current point, // with coordinates relative to the // center of the polygon. vec2 coord = gl_FragCoord.xy; coord -= center; vec4 imagePixel = texture2D(src,gl_FragCoord.xy); // The content to use for what's in the polygon, and what's outside. vec4 pIn = drawn == 1 ? imagePixel : color1; vec4 pOut = undrawn == 1 ? imagePixel : color2; if(drawn == 2) // drawn area is "nothing"? make it the undrawn area no alpha { pIn = pOut; pIn.a = 0.0; } if(undrawn == 2) // undrawn area is "nothing"? make it the drawn area no alpha { pOut = pIn; pOut.a = 0.0; } // Introducing Theta and Omega. // // Theta is a circle divided by sides, // so, 90 degrees for a square, or // 72 for a pentagon, &c. // // Omega is the angle from the polygon // center to the current point. // // (Later on, Omega2 is the angle within the // rounded corners, a much tigher curve.) float pi = 3.14159265358979323; //float sides = 7.0; float theta = pi * 2.0 / float(sides); float omega = atan(coord.y,coord.x); // angle of current point from center // turn it, so we can rotate a polygon... // round omega to be the nearest polygon corner // (first, turn the polygon, and add a half so the "neutral" position is edge down) float turnsMod = radians(rotation) + theta / 2.0 + pi / 2.0; omega = theta * floor((omega + theta / 2.0 - turnsMod) / theta) + turnsMod; //omega = mod(omega + pi,2.0 * pi) - pi; float omegaSin = sin(omega); float omegaCos = cos(omega); mat2 rot = mat2(omegaCos,-omegaSin,omegaSin,omegaCos); // thetaNext is the angle to the next point, based on sides & pointiness float thetaNext = theta * (1.0 + pointiness * (float(sides) / 2.0 - 1.0)); // For a particular corner radius, we reduce the // edge radius by a different amount, and add it // back later for the un-rounded parts. This // amount we pull in the corners, cornerPull, is // more than the corner radius. float cornerPull = roundness * radius; float cornerRadius = cornerPull * cos(thetaNext / 2.0); cornerPull = min(cornerPull,radius); rot *= (radius - cornerPull); // p0 is the nearest corner, surrounded by p1 above, and p2 below. // the current point will be evalated based on distance to // those two edges (that is, p0 to p1, or p2 to p0), or distance // from the inset corner, if it's close enough vec2 p0 = vec2(1,0) * rot; // nearest corner vec2 p1 = vec2(cos(thetaNext),sin(thetaNext)) * rot; // upper edge vec2 p2 = vec2(cos(thetaNext),-sin(thetaNext)) * rot; // lower edge // distances from each line segment; postive outside, negative inside the poly. float distP1 = distanceFromLine(p0,p1,coord); // distance from nearest edge, up float distP2 = distanceFromLine(p2,p0,coord); // distance from nearest edge, below float inOrOut = max(distP1,distP2); // But! Is the point near the corner? // If so, round it by the corner radius. // // We want to say, is omega - theta/2 < omega2 < omega + theta/2, // but because of pi and -pi wrapping, we figure the difference instead. float omega2 = atan(coord.y - p0.y,coord.x - p0.x); float cornerA = mod(omega2 - (omega - thetaNext / 2.0),pi * 2.0); bool inCorner = cornerA < thetaNext && roundness > 0.0; if(inCorner) { float distP0 = distance(p0,coord); // distance from the inset corner inOrOut = distP0; } inOrOut -= min(radius,cornerRadius); float ringSpacing2 = ringSpacing + strokeWidth; if(inOrOut > ringSpacing / 2.0) { float ringNumber = inOrOut / ringSpacing2; if(ringNumber < ringCount) { inOrOut = mod(inOrOut - ringSpacing / 2.0,ringSpacing2) + ringSpacing / 2.0; if(inOrOut >= ringSpacing / 2.0) inOrOut -= ringSpacing2; } } // at this point, inOrOut is negative for areas // inside the polygon, positive for outside. // blend by Edge-pixels worth between them. // & we're done. if(strokeOrFill > 0)// || (ringNumber >= 1.0))// && ringNumber <= float(ringCount))) { inOrOut = (abs(inOrOut + strokeWidth / 2.0) * 2.0 - strokeWidth); } inOrOut = smoothstep(-edge, edge, inOrOut); gl_FragColor = mix(pIn,pOut,inOrOut); }