fhtr

art with code

2015-02-26

Get 11 live wallpapers for the price of one! (And there's more on the way!)

Get the Opus Live Wallpaper Pack now for $0.99

These fully animated live wallpapers transport you into the strange dream-world of Opus and let you escape the daily humdrum of existence. Relax during a busy day by watching one of these ambient animations.

Available on Android today! Head on over to the Play Store and get the wallpaper now. Take advantage of the 15-minute money-back guarantee at Play Store and use the wallpaper for a bit, risk-free! Opus Live Wallpaper Pack

Tell your friends about this amazing deal & share this post! Thanks :D

2015-02-20

New effects in Opus Live Wallpaper Pack

I added a bunch of new wallpaper effects to the the Opus Live Wallpaper Pack. You can preview some of 'em on fhtr.org, have a look! If you've got a nice Android phone and want to make it nicer, get the Opus Wallpaper now for $0.99 from the Play Store ;)

2015-02-15

Bouncing Heart Live Wallpaper

Just released a new Android live wallpaper called "Bouncing Heart", since, well, it's got a heart that bounces. Very Valentine's day, no?

It's all one big fragment shader, ready to turn your phone into a wonderland of shiny pink hearts, etc. Give it a try, maybe it'll cheer you up. It's free!

If you've got the pro version of the Opus Live Wallpaper Pack, the Bouncing Heart is one of the wallpapers included in the pack. You totally want to buy it because it's awesome!

2015-01-18

Three notebook system - part 1 / 3

In the past few years, I've started to gravitate towards a work scheduling / external memory system to keep my projects rolling smoothly. What I've got going now is a three notebook system, which, as you might guess, revolves around three notebooks. Let me give you a brief overview of the system.

I use the three notebooks to record what I plan to do, what I should be doing next and what I have done. The notebooks operate on different timescales. The planning notebook is concerned about quarterly plans. It moves along at a very leisurely pace. The daily notebook sets goals for the day and the week. It's got roughly a week's worth of goals on one spread. The third notebook is the work log. It records what I've been doing, how long it took to do it, and what I learned in the process.

When I start my day, I take a quick look at the planning notebook to remind myself of my medium-to-long-term goals. Then I write the first few tidbits to the work log: simple stuff like "6:30 Woke up, breakfast, shower. 7:30 Start of day. 7:45 Made Opus SA icons in Photoshop. 8:00 -> Write daily goals [x] ...". At the start of the day, I write my goals for the day into the daily notebook. At the start of the week, I also set some higher-level goals for the week.

The level of detail in each of the notebooks is quite different. The planning notebook deals in high-level plans and their measurable results. In it, I write strategic goals with planned quarterly-level tactics on achieving those. The daily notebook has weekly goals that support the quarterly tactics and daily goals that deal with the minutiae of scheduling and achieving the weekly goals. The work log acts more as a short-term memory extension. I use it to plan my next action during the day, keep myself focused and maintain a sense of progress.

With the three notebooks I've got guidance on where I'm headed in the future, what I'm planning to do this week, what I'm going to do today and how that's working out so far. The big idea here is to try and align my short-term actions to my long-term objectives.

As I progress through time, I tweak the goals as the situation changes. Tweaking the goals in turn tweaks the daily goal planning. The goals for the previous days are not the goals for today. This flexibility gives me the ability to respond to changes rapidly without losing sight of the long-term goals.

In conclusion, the three notebooks keep me focused on what I'm doing now and how that's going to help me in the future. The notebooks act as goal-oriented external memories at different timescales. By keeping track of my use of time, they also give me a better sense for how long it takes to do things.

I'll take a closer look at each of the notebooks in part 2 and go through the practical experience in part 3. Thanks for reading! What kind of planning systems do you use to get your work done?

2015-01-13

Opus Live Wallpaper

I ported a bunch of the fhtr.org effects over to Android to use as a live wallpaper. The wallpaper is available on the Google Play Store as either a $0.99 version or an ad-funded version (hey, there's also a small fireworks wallpaper with a web preview). My total income from these over the last month has been a bit less than $5, so, well, it's been more educational than anything else :D

The effects look like the pictures below or the video above. I like having them as wallpapers, gives a nice feel to my phone. You probably need something like an Adreno 330 to run them well, so phones like LG G2 and above.

Porting the shaders over from WebGL was easy for the most part. There were a whole lot of performance tweaks that I had to apply. One of the most important ones was rendering into an FBO at a lower resolution and then upscaling the FBO to screen res. With HiDPI displays, the difference between full res and scaled up is not very drastic.

Another technique I used was rendering at a lower framerate. The prob there is that you want to keep the main UI interactive while you're rendering. If you do it naively with "render frame -> wait 2 frames -> render frame -> ...", and the "render frame" bit takes longer than 16ms, you'll cause the main UI to skip frames. Which is bad. The solution I arrived to was to render a part of the wallpaper frame during the main UI frames, then display the finished frame in the end: "render 1/3 of frame -> render 2/3 of frame -> render 3/3 of frame & display it -> ...". This way I can keep the main UI interactive while rendering the wallpaper frame.

But we're not out of the woods yet! Some wallpapers have a central part that is very heavy to render and edges that are cheap. If we split the frame into e.g. 3 slices, one of the slices would take the majority of the time, and potentially cause the main UI to skip frames. So we need to find a split that distributes the work equally among the UI frames. To do the partial frame rendering, I slice the frame into 8 px vertical stripes. On each UI frame, I render the wallpaper stripes belonging to that frame (frameNumber % numberOfUIFramesPerWallpaperFrame == 0). As the UI frame number increases, the renderer moves across the wallpaper frame, drawing it in an interleaved fashion. This gives me a fairly even split of work per frame and gets me a consistent frame rate for the UI.

If you have a try at the wallpapers, lemme know how it goes. Would be super interested in hearing your thoughts.

2014-09-06

In which I make videos

Edited a video with After Effects.

Proceeded to follow a motion graphics tutorial.

And then I started making a website. Country life!

What the hey

Recently: Writing a web app backed by a bunch of CGI programs written in Haskell, running on Mighttpd2, a web server written in Haskell. And a whole lot of JavaScript to make it run. It's using PostgreSQL to store its stuff.

What the app does: It's a website with a shop component. You can edit the pages by writing HTML into text fields. Yeah. Let's shake our collective heads together.

How's it going: I like writing Haskell though I don't like the Cabal dephell. I probably have to use a different web server as the Mighttpd2 version in Ubuntu 14.04 doesn't do HTTPS and I haven't had luck installing a HTTPS-supporting version from Cabal. Eh. JavaScript is as usual, difficult to keep sane. CSS helps keep the JS less gnarly. I kinda like the little experiments in the page structure. First I had all the site content inlined into a single page, then I moved them out to HTML files that the JS pulls in (and inlined the front page using a build script). Then I moved the HTML files into a database and now I'm fetching all of them in a JSON array at page load, so it's sort of going back to the inline-everything-thing.

How about that shop: The shop part is building shopping carts for PayPal checkout. Which does work, though a completed payment should also ping the server to update the inventory.

How it does what it does: The client does all the interesting bits. The server just serves JSON from the database. The admin client edits the JSON objects it receives from the server and sends them back to save them. The cool bit is that Aeson, a Haskell JSON library, typechecks the whole thing, decoding and encoding the JSON with a minimum amount of code on my part.

-- ListPages.hs
-- GET -> JSON

-- Returns a JSON array of pages.

import Network.CGI
import Data.Aeson
import PageDatabase
import SiteDatabase

instance ToJSON Page

main = runCGI $ handleErrors cgiMain

cgiMain = do
  setHeader "Content-Type" "application/json"
  setHeader "Access-Control-Allow-Origin" "*" -- set CORS header to allow calls from anywhere
  liftIO listJSON >>= outputFPS

listJSON = fmap encode $ withDB listPublishedPages

-- listJSON :: IO Lazy.ByteString
-- listPublishedPages :: Connection -> [Page] -- fetches the list of pages from the database where published = true
-- Data.Aeson.encode turns [Page] into a ByteString of JSON.
-- See the "instance ToJSON Page" above?
-- That is all I need to do to get type-safe JSON encode and decode.
-- As long as I use "deriving (Generic)" in my type definition, that is.

Here's the Page data type from the PageDatabase module:

data Page = Page {
  page_id :: Int64,
  bullet :: String,
  body :: String,
  published :: Bool
}  deriving (Show,Generic)

This is how I deal with the JSON that the client sends:

-- EditPage.hs
-- POST (Page) -> JSON true | false

import Control.Monad
import Network.CGI

import SiteDatabase
import PageDatabase
import SessionDatabase
import GHC.Int
import Data.Aeson

instance FromJSON Page -- Make Data.Aeson.decode parse JSON into Page objects.

main = runCGI $ handleErrors cgiMain

cgiMain = do
  body <- getInputFPS "body"
  authToken <- getAuthToken -- helper that deals with session cookies, CSRF tokens and login user/pass params
  msg <- liftIO (maybe noPage (editPageDB authToken) (body >>= decode)) -- decode turns the body JSON into a Page object
  setHeader "Content-Type" "application/json"
  output msg

noPage = return "false" -- No body param received or the body param failed to typecheck in decode.

editPageDB authToken page = do
  rv <- withDB (\conn -> authenticate conn authToken (editPage conn page)) :: IO Int64 -- authenticate runs editPage if the authToken is OK
  case rv of
    1 -> return "true"  -- Edit successful
    _ -> return "false" -- Page not found or auth failed

Isn't CGI kinda slow: Dunno. Testing on an EC2 micro instance, a HTTP request for a JSON array of all the ten pages in the DB takes about 10 ms.

Couldn't you just use Weebly / Squarespace / Wix / Whatever: Hey! Watch it! No! Of course not!

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.