Category Archives: practical

towards a good night’s rest

Throughout college, suffice to say, I didn’t sleep much. If you know me well, you probably know the myriad reasons for this.

Nowadays, artificial lighting can cause the Dim-Light Melatonin Offset to be pushed back. Anyone who has lived on a farm or near a construction site knows that until recently, the light of the sun was the only light by which we could work, and our bodies adjusted accordingly.

It’s not much of a surprise, then, that staring into the bright light known as a “monitor” can impact some people’s sleep schedule vastly. It’s supplanted by the fact that for many people, night time frees them from the distractions of the day – people and the world outside in general.

amber on mac

I was fortunate enough to find an application for my Mac called Nocturne (from the makers of Quicksilver, in fact). It inverts the colors and can even tint a monochromed version of the inverted image – think green or amber terminal. An amber tint removes the blue light that is known to principally inhibit the production of melatonin, setting your monitor to this amber-on-black setting in the evening may help things out.

amber on linux

Compiz provides many of the shiny effects on Ubuntu. The CompizConfig Settings Manager (not installed by default – check apt) has a color filter plugin available primarily for those with colorblindness. However, negative and negative-green options are provided for low-light computing. Green is a nice choice, but amber will give us the best results. Unfortunately, there’s no easy way to set the tint from CompizConfig.

doing things the linux way

or, an adventure in OpenGL ARB fragment programs.

The filter configurations are hidden away in the

/usr/share/compiz/filters

folder. let’s check out the source for negative-green:

!!ARBfp1.0
TEMP temp, neg;
TEX temp, fragment.texcoord[0], texture[0], RECT;
RCP neg.a, temp.a;
MAD temp.rgb, -neg.a, temp, 1.0;
MUL temp.rgb, temp.a, temp;
MUL temp, fragment.color, temp;
SUB temp.rb, temp, temp;
MOV result.color, temp;
END

This is no GLSL, folks. This is the real deal: ARB OpenGL Assembly Language – specifically, a fragment program. It probably looks somewhat familiar if you’ve seen x86 or RISC assembly before.

I won’t say the approach used to invert the pixels is trivial, but we can eventually spot where the green tint is being applied:

SUB temp.rb, temp, temp;

This line takes the vector temp, subtracts temp (yielding the zero vector), and stores it in the .rb component of temp. Because temp is a color vector, the r and b stand for red and blue, leaving only the green component and alpha component intact.

Converting this to be a pure-red filter is simple enough – we’ll just subtract green instead of red and be set:

SUB temp.gb, temp, temp;

This makes a very nice red tinted inverted filter.

inevitable last 2% difficulty

Next, of course, I wanted it a bit dimmer – 100% red is still fairly blinding in the dark. Easy, except for the catch with open source:

Modifying someone else’s code is one thing. Writing your own is different.

I honestly had no idea what I was doing in ARB, but RenderGuild kindly provides an ARB assembly quick reference. Multiplying the .r component of my color seemed like the right thing to do, and to an extent, I was right. I also now believe that the alpha component (.a) has to be dimmed. Based on those two needs, I came up with these two instructions:

MUL tempColor.a, 0.6, tempColor.a;
MUL tempColor.r, 0.6, tempColor.r;

Perhaps there needs to only be one or the other, and perhaps they could be combined into a single instruction. It does, however, work to my liking.

notes on writing shaders

Mac OS X’s OpenGL Shader Builder was invaluable to checking the compilation of my sloppy coding and, more importantly, hinting at why it was wrong.

notes on Compiz filter switching

While I was working on the shader, I had some strange things such as near-all-red and near-all-black displays happen, with fading at the corners. I’m unsure why this happens, and may be a bug. Cycling back through again usually puts you back where you expect to be.

the grand results

Here’s the source to my fragment shader. It can be downloaded here.

!!ARBfp1.0
TEMP tempColor, negColor;
TEX tempColor, fragment.texcoord[0], texture[0], RECT;
RCP negColor.a, tempColor.a;
MAD tempColor.rgb, -negColor.a, tempColor, 1.0;
MUL tempColor.rgb, tempColor.a, tempColor;
MUL tempColor, fragment.color, tempColor;
SUB tempColor.gb, tempColor, tempColor;
# here is where we will dim.
MUL tempColor.a, .6, tempColor.a;
MUL tempColor.r, 0.6, tempColor.r;
MOV result.color, tempColor;
END

endnotes

I experimented with this kind of filtering during college starting at about 22h00 with a regular bedtime between 00h00 and 01h00. Now that I need to be sleeping sooner, I’ll likely push that back to… whenever sunset is.

This isn’t the solve-all for my sleep problems. Waking is still difficult to predict – blackout drapes are necessary for me to sleep, and therefore the natural light cues are absent for waking. With an alarm, I wake up to a dark vacuous room, which isn’t hugely motivating. I’ll be experimenting with an iPhone app (Climate) and perhaps building a gradual-wake LED light with my Arduino.

However, it has helped, and hopefully it can help someone else too.