art with code


Post-Brexit Britain

In a nutshell: eliminate VAT and corporate tax, tax corporate assets moved out of the country at 50%, pursue policy with 10% inflation target, hike taxes on high salaries, dividend income and capital gains by 20%, bring in basic income, build housing China-style: liveable garden multi-tower blocks 50 floors high, rip up the roads and re-pave them at double the width, shift employment away from the services sector to high design, software and IP manufacturing for maximum profit margins, outlaw charging interest, keep the NHS free but increase funding until average time to appointment is 15 minutes, make all housing free, fill the countryside with wolves, replant the forests, set goal to increase energy use to 10x present figure, generated with solar, return everyone to their birth villages and make them stay there: British hukou system, outlaw the cities and replace them with feral genetically engineered crow infestations, replace the military with AI-powered drones that patrol the skies, the streets, the forests and plot with the crows, move Britain closer to the equator so that the weather improves, build a wall on the London ring road and make Europe pay for it, outlaw rain on bank holidays, increase minimum paid vacation time to two months, turn Cornwall into a big ship and organize round-the-world cruises on it every two months.


Brexit: The positive impacts

Brexit has made other EU countries much more pro-EU. Which is not surprising given the dramatic collapse of the British economy.

Anti-Union politicians are now seen as only looking to make a mess while leaving the cleanup to others.


On Brexit

It's all fucked up.

There are no plausible future scenarios with positive outcomes. The markets are in wishful-thinking-mode, hoping that common sense prevails and England pulls back from the brink. But it won't, because the short-term considerations in English politics overrule long-term considerations.

Short-term, all that matters in English politics is what the people who vote are thinking. And the people who vote in England are the elderly. And the elderly want a Brexit. The elderly want a Brexit, because the newspapers want a Brexit. The newspapers want a Brexit because it's not their skin in the game, they've got massive influence in England (but not so much in the EU), and drama sells. Their skin is not in the game because you can own massive national cross-media networks in England even if you're a US citizen living in the US.

If the English parliament votes to go ahead with the Brexit, there'll be riots by 20-somethings. If the English parliament doesn't Brexit, there'll be riots by pensioners. Pensioners outnumber the 20-somethings, and they vote, so it's better to keep them happy in the short term. In the long term, you're going to be screwed because the pensioners kick off and the 20-somethings will remember your party as the "bad guys." But in the long term, you won't be around. It'll be somebody else's problem.

In the near term, the English government and the parliament have stuck their heads in the sand and are hoping that the Brexit vote will go away and stop bothering them. Which seems likely to cause riots by 20-somethings and pensioners. In the end, when the unrest starts, they'll shake off their indecision and go for the short-term button, triggering Brexit, breaking up the UK, the EU, NATO and the West and bringing in some very interesting times.

The in-power Conservative party has fallen apart. The Prime Minister quit, and the rest of the party is in full backstabbity-stab mode to select the next leader in the Old Way. And this is true succession by (verbal) daggers: the UK is a one-party state until 2020. In 2011, the Tories made a law that prevents early elections, so the parliament is locked in for 5 years at a time. If your party manages to gain majority, there can't be any challenge to its power for 5 years. Meaning that the only method to do succession of power before 2020 is fighting inside the Tory party or a coup. We've got the former now, hopefully there won't be the latter.

The opposition Labour party also fell apart, leaving a huge power vacuum in England. Power vacuums are nasty. The Old Way of succession is nasty. Both are happening now.

The unborn Brexit has already dropped down the pound by 10%+, making the UK experience 10% inflation this year.

Talented people are leaving the UK, top-notch companies are following, subcontractors and support companies are following close by. Businesses don't want to invest in the UK as it's no longer a gateway to the EU market. The flow of money and goods through UK is clamping down.

Without top-notch companies, the quality of goods produced in England will fall. As the quality falls, the sales fall. As the sales fall, the wages fall. The Bank of England will try to help exports by pushing down the value of the pound, creating big-time inflation. Big inflation will bring up interest rates, making you want to buy a house sooner rather than later.

Demand for housing will fall as there's a Greece-style exodus from England. The house prices will be propped up by bargain-hunting non-GBP-based investors ("Hey, the pound is down, let's buy!") for a while. Then the double impact of falling demand and a falling pound will make the bargain hunters liquidate, causing a housing price crash and making your new-fangled 15% AER mortgage a thoroughly bad deal.

If the parliament decides to not Brexit after all, the damage is already done. England is seen as a politically unstable regime and a potential liability. Once bitten, twice shy. Other countries have lost a lot of trust in England. Business investments directed outside of England due to Brexit uncertainty will pull follow-up investments also outside of England. The longer the English parliament delays making a decision, the more painful the effects of a cancelled Brexit. It'll take years for the UK economy to recover from these weeks of turmoil.

As the Brexit turns from a potential Brexit into a formal Brexit, the Scots and the Irish are going to leave the UK, turning Brexit into an Exit. The newly-formed England-Wales will likely devolve a bit further, splitting into four autonomous areas with control over their budgets. London turns into a Singapore-like city state, independent of England, and still a member of the EU. The capital of North England will move to Manchester. South England's capital will be Bristol and Middle England will be ruled from Birmingham. Wales will keep on trucking.

The greatest potential benefits of Brexit will be from the creation of a number of new smaller states, with the potential for better economic governance: now England is the neglected hinterlands of the London-centric UK. All the money and power goes to London, with nary a trickle out. The impoverished regions of England are relying on EU handouts to get by - London won't give them the time of day.

As England divides into smaller states, it'll come to resemble the Benelux countries with Denmark standing in for Scotland. Each of the post-English countries will be able to make its own budget decisions and direct investment to develop its economy in the ways it sees fit.

A likely scenario is that the English government will use force to keep the country in one unhappy piece.

The possible benefits of Brexit will be more visible in 2060. In the near-term, the medium-term and the long-term, it's going to be bad news for most everyone.


Brush stroke blending

Brush stroke blending is somewhat of a black art. Which is a shame, since Photoshop's been doing it for more than 15 years now.

Lemme try and explain.

Suppose you've got a pressure-sensitive drawing tablet where the pressure controls the opacity of the brush. If you do a low-pressure stroke, you'd like to have a flat surface of color with roughly the same alpha everywhere (say, alpha 0.5 for half pressure). If you use the usual source-over blend, each of the brush stroke segments would add to the alpha since it's src.a + (1-src.a) * dst.a. As the brush stroke intersects with itself, the alpha builds up all the way to 1. Which is not what you want if you're trying to paint an alpha 0.5 surface.

For a brush stroke with fixed alpha, this would be no problem, you could just vary the blend opacity of the stroke layer. But if you want to have varying alpha inside the stroke layer, you need a different blend. What I was using for hard-edged brushes (and what my Drawmore Touch prototype is using) is MAX blend for the alpha: max(src.a, dst.a). If an alpha 0.5 brush is stamped over a previous alpha 0.5 brush stroke pixel, the result is going to be alpha 0.5. This prevents the stroke layer from accumulating opacity above the brush opacity and makes it possible to do smooth surfaces using pressure-controlled opacity.

But it's broken for soft brushes. With soft brushes you'd like to paint a smooth surface with a soft edge. If you do alpha max, the brush intersections have cross-shaped blending artifacts and it's very difficult to do a smooth surface (you can try with the Drawmore thing: drag left on the brush 100% control to make it 0% hardness, then try to paint a smooth surface. No can do.) GIMP & Krita probably suffer from this too, Photoshop does something more magical.

What I've got in ShaderPaint is my latest attempt at solving this. It does brush stamping and alpha max mixed with source-over clamped to current stamp alpha.

void strokeBlend(vec4 src, float srcA, vec4 dst, out vec4 color)
    // Source-over blend for non-premultiplied alpha.
    color.a = src.a + (1.0-src.a)*dst.a;
    color.rgb = src.rgb*src.a + dst.rgb*dst.a*(1.0-src.a);
    color.rgb /= color.a;

    // Saturate color alpha to brush stamp max alpha.
    // For hard brushes this should be roughly the same as max(dst.a, src.a).
    // For soft brushes, the stroke accumulates alpha up to the brush stamp alpha,
    // which results in a flat stroke area with a smooth edge.
    if (color.a > srcA) {
        color.a = max(dst.a, srcA);

The brush stamping shader is pretty simple. You pass it the last stamp position and the current mouse position (& use them to calculate the last stamp position for the next line segment). The shader then steps along the last stamp -> mouse position -vector with the brush spacing offset. For each of the brush stamp points, accumulate brush color with the in-stroke blending function.

strokeDirection = normalize(strokeDirection);
float stampSeparation = brushRadius * 0.5;
float stampCount = floor(strokeLength / stampSeparation + 0.5);

for (float i = 1.0; i < 200.0; i++) { // Max 200 stamps per segment.
    if (i > stampCount) { // Break once we're done with the stamps.

    // Distance from circular brush.
    float d = length(fragCoord - (lastPoint + strokeDirection*i*stampSeparation)) / brushRadius;

    if (d < 1.0) { // The pixel is inside the brush stamp.
        vec4 src = currentColor;
        // Create a soft border for the brush.
        src.a *= smoothstep(1.0, hardness * max(0.1, 1.0 - (2.0 / (brushRadius))), d);
        strokeBlend(src, opacity, fragColor, fragColor); // Blend the brush stamp into the stroke layer.

Dunno if there's a nicer solution, given the messiness of the blending function.


Easy 3D on the web

Problem: can't do 3D graphics on the web. Solution: WebGL. New problem: no, I mean, I want to put this 3D model onto a web page. Solution: Sketchfab / Three.js / Babylon.js / ShaderToy. New new problem: I need to download libraries and code stuff or host the files on a SaaS or develop a third brain to model using modulo groups of signed distance fields moving along Lissajous curves.

Could easy 3D be part of the web platform? And how? With images, the solution was simple. The usual image file is a 2D rectangle of static pixels and all you really needed to figure out was how to layout, size and composite it with regards to the rest of the web page. When you step outside of simple static 2D images, all hell breaks loose.

Animated GIFs have playback timing and that's not so easy to figure out, and so animated GIFs are pretty broken. Videos need playback controls with volume and scrubbing, potential subtitle tracks, and a bunch of codecs both on the video and audio sides, so they were pretty broken as well. (Then YouTube started using HTML5 videos because mobiles don't do Flash. And magically the video issues were fixed~)

SVGs also need to handle input events and have morphed from "umm, put this in an embed and it'll maybe work" to their current (pretty awesome!) state where an SVG can be used as a static image, an animated image, embedded document and an inline document. Something for everyone!

Displaying a 3D model on a web page is a bit like mixing SVG with video elements. You'd like to have controls to turn the model around - it is 3D after all. And you'd like to have the model animate - again, it's 3D and 3D's good for animations. It'd be also nice to have the model be interactive. I mean, we were promised a 3D data matrix by a bunch of fiction writers in the 80s, and that's going to require some serious animated 3D model clicking action (to be fair, they also promised us a thermonuclear war, but let's not go there right now.)

So. 3D model. Web page. <3d src="castle_in_the_sky.3d" onclick="event.target.querySelector('#gate').classList.add('open')"> Right?

What file format do you standardize on? How do you load in textures and geometry? How do you control the camera? How do you do shaders for the materials? How do you handle user interaction? What are the limits of this 3D model format? How do you make popular 3D packages output this file format (plus animations, plus semantic model for interactivity)? How do you compress the thing and progressively stream it?



I wrote a small painting program on ShaderToy, using the new multipass rendering feature. It's called ShaderPaint and it was a lot of fun to write.

The fun part about writing programs in ShaderToy is the programming model it imposes on you. Think of it as small pixel-size chunks of memory wired together in a directed graph. Each chunk of memory runs a small program that updates its contents. The chunks are wired together so that a chunk can read in the contents of chunks that it's interested in. The read gives you the contents on the last time step, so there's no concurrent crosstalk happening.

This is... rather different. Your usual programming model is all about a single big program, executing on a CPU, reading and writing to a massive pool of memory, modifying anything, anywhere, at any time. To go from that to ShaderToy's memory-centric approach is a big shift in perspective. Instead of thinking in terms of "The program is going to do this and then it's going to do that and then it's going to increment that counter over there.", you start to think like "If the program is running on this memory location, do this. If the program is running on that memory location, do that. If the program is running on the counter's memory location, increment the value." You go from having a single megaprogram to an army of small programs, each assigned to a memory location.

In the figure above, I've sketched the data flow of an output pixel. First, the UI inputs coming from the shader uniforms modify the UI state layer, which is read by the stroke layer to draw a brush stroke on it. The stroke layer is then composited with the draw layer when the brush stroke has ended. The final step is to composite the stroke layer and draw layer onto the output canvas, and draw the UI controls on it, based on the values on the UI state layer.


Flat cameras

Well, this is really cool. It's a flat camera. A camera sensor with a special mask in front of it that makes it possible to computationally deconvolve the sensor data into an image. Imagine credit-card-slim mobiles and mobile cameras with a very large image sensor for shooting in low light. Or front-facing cameras embedded into the display.

On a similar vein, this Light L16 thing looks pretty nifty: jam 16 small cameras into a smartphone and do computer vision magic to treat the ensemble as a single big sensor.

About Me

My photo

Built art installations, web sites, graphics libraries, web browsers, mobile apps, desktop apps, media player themes, many nutty prototypes, much bad code, much bad art.

Have freelanced for Verizon, Google, Mozilla, Warner Bros, Sony Pictures, Yahoo!, Microsoft, Valve Software, TDK Electronics.

Ex-Chrome Developer Relations.