Going on with the same theme as in my last post, only that this time it’s all based on vector graphics.
The principle is very loosely based on this article, or at least inspired by it …
Basicly it’s all about ray tracing on a rectangular grid: finding the intersection with the next cell wall:
The projection used is like in panorama cameras, a cylinderic one. Try setting the parameter ‘focal length’ to a very small value and you’ll see things getting really ‘Escher’ or ‘Piranese':
I admit it is a bit slow on performance …
In principle this is the same effect I already did with html5/canvas. Now it’s time for Pixel Bender to try some serious image bending.
Click on the image above to go to the demo.
Ok, drawing a spline, or more generally rendering graphics along a spline, is relatively simple if you can explicitly calculate points of it and draw it part by part using lines, gradients or piecies of an image.
But it all becomes much more challening when in an environment, like Pixel Bender, where you can only go through the image pixel by pixel – and take the implicit approach.
If we where dealing with a line or a circle, calculating the distance to it would be so easy, but points on a Bezier are defined by a parametric cubic polynomial, and there’s no way to solve the inverse process algebrally. So what to do? There has to be some way to map the screen coordinates to a Bezier system:
Ok, looking at a picture always helps. Let’s say our current point is the black dot on picture and the Bezier passes on the top of the grid as the blue line. First we find the nearest point on the curve, below ‘x’ where blue and red line meet. Distance to that, the red line, would be the new coordinate y. Then we calculate the distance along the path to that nearest point (blue line), length corresponds to coordinate x. Both of these calculation are ‘impossible’ to write as single evaluations, so we need some approximation.
From the curve we know the start and end points and the directions at both, so let’s start with this piece of information. We count, using dot product of two vectors, the cosine of angles between directions and the distance vectors to current point. If this value has different signs on the ends, current point lies somewhere in between, and we’re looking for the point where the value goes to zero.
Using values the start and end we approximate a point in between, repeating this a couple of times converges to a point where cos γ ≈ 0.0. For most cases this is a reliable result, although we totally neglected the fact that Beziers can even form closed loops, those cases would require splitting the curve to several sequences by points where x”=0 or y”=0. I mean the code should check out three candidates for the closest point.
My pixel bender-kernel repeates the iteration three times, which I think is adequate enough for the purpose of a computer graphics demonstration. In fact the method slightly differs from the principle I described, that’s only because also wanted to add the effect for rotating the image around spline’s main axis.
The mystery to solve here is a system of two nonlinear equations. You could also try solving that with like for instance Euler iteration using Jacobian determinate. The problem with that method is that it easily tends to converge to unwanted solutions, to points somewhere far from the actual spline sequence. Remember that Bezier is a continuous curve, where we only see the sequence from t=0 to t=1.
Ok, back to task. We now have the distance ‘y’. We need also the ‘x’, so all we need to do is just to calculate the distance from start point:
But now wait a minute, that’s an Elliptic integral or something else as awful — unfortunately there’s no build-in function for it in Pixel Bender. So we’ll use Simpson’s rule to get some idea of the length. In the simpliest case of that we calculate the sum of (value at start +3x (values at point of one third+value at point of two third) + value at end)/8. And to my surprise looking at the result it is enough!
I looked at the result with a more precise approach: sampled at 7 points with weights 1,3,3,2,3,3,1 – visually there was hardly any difference. In the demo same method is used when fitting an image’s width to spline’s length. It is said that Simpson perfectly approximates a cubic polynomial. In the formula x(t) and y(t) are cubic polynomials, which makes x'(t)² + y'(t)² of degree four, and square root of that could be something close to quadratic – at least that’s how I explained it to myself.
As a conclusion. This is probably the stupidiest way of drawing by a spline: There are still errors in more ‘knotty’ cases. Furthermore the shader has to go through the entire bitmap to render even a smallest curve.
At least inside Flash Player much better results are obvious obtained by using methods of graphics like in my earlier post in case of 2D. Anyway I wanted to post it here, even if nothing else as an example of solving some awful mathematics.
Click on the images above to go to the demo.
After publishing some earlier posts like this I received an e-mail of how to create this kind of pattern.
After taking some time to consider the geometry and making a couple of attempts,
I came up with the code I’m now publishing.
View the sources here. Download sources.Pixel Bender -source code. Pixel Bender -filter.
And that’s not all yet. There’s also another version. What happens if we add a transition to parameter ‘radius'; we slide its value, let’s say like for instance from left to right ?
Well this, surprisingly effective result with quite simple means:
Generally this effect is at its best with graphics like text elements or on the World Map used as a default. Technically the filter first creates a normal map based on brightness values, the sample sizes are 3×3, 5×5 and 7×7 – smallest works best with very detailed images, largest for text elements. Secondly a phong-like shading is applied to that.
The shader takes two bitmap inputs:
instead of having a number of different parameters for the material appearance, I’m using a small bitmap stripe as a checkup table for the shading:
so that if current point is found in a complete shadow, the stripe is sampled from left edge, if on highlight, the right edge, and otherwise somewhere horizontally along the image.
Here are the bitmaps for some materials in demo:
View the sources here. Download sources.
The demo also allows to add a special effect on the background — making it look like grainy, wavy or bumpy — on images with alpha channel.
That’s not a PB-effect, it was created in actionscript by adding noise or perlinnoise on the back.
It just looks so nicely realistic like a metal sheet really was sandblasted or hammered.
This filter is probably the weirdest combination of complex inverse-maths and circle packing I’ve ever coded.
The rational function evaluated here is z= d/[(z-a)(z-b)(z-c)]. This kind of mapping on complex plane are conformal – that means the angles remain the same.
In the demo you can change the parameters a,b and c by dragging the blue grips on stage.
Where parameter d as a complex number is located on the unit circle |d|=1, is has the effect of rotating the output.
Click on above image to go to the demo, and have fun modifying the parameters. But hey, warning and please be careful: The results might get really artistic sometimes:
This filter is some weird combination of complex inverse-maths and circle packing.
Click on above image to go to the demo. There are parameters to modify the circle shape ratios and the amount of how much of a circle’s area is filled.
Just like in my previous blog entry Cairo Tiling, Floret Pentagonal Tiling is made out of pentagonal tiles. Unlike in many other surface filling tilings, here the polygon is not regular. It’s more like a hexagon where one edge is stretched out.
Click on above image to go to the demo.
The principle of doing that with code is to first create a regular hexagonal tiling. Get the integer coordinates for current hexagon and evaluate the ‘magic’ modulo function (x+4y)%7. All the cells in a neighborhood of seven hexagons loop through numbers 0 to 6.
Using this result we can easily drop out the zero cell in the middle by handling it in a different manner, and get to the Floret pattern. It’s just so simple: just look at the awfully messy pbk-source code to get even more mixed up that you already are.
When it comes to code, this is slightly different from Cairo Tiling: it uses adding a ShaderFilter on array ‘filters’ of a displayObject, while this uses ShaderJob to get the effect.