Search this blog

12 January, 2011

OT: DXOLabs / Luminous Landscape is wrong

DXOLabs is a company devoted to digital camera and lens testing software. Their DXOMark is a standard for lens testing, and they surely know their business.

So you might imagine that when you read an article on a well respected website, as Luminous Landscape is, that tells you that your loved (and expensive) digital camera is cheating you, it's something to worry about.
The article is "An Open Letter To The Major Camera Manufacturers" by Mark Dubovoy. The thesis is that the digital sensors, having the photosites somewhat inside a "tube" are shielded from some of the peripheral light rays (think of a honeycomb grid on a flash), so very fast lenses hit this limit and become "darker". Thus the camera manufacturers hacked the problem by silently raising the ISO sensitivity with such lenses.

This is interesting and so on, but it sounds strange. The graph they gave Dubovoy seem to depend only on the f/stop and not on the design and focal of the lens (latest data is here). If the problem is the angle of the light rays, wideangles should be more affected than tele.

Anyway, I had to test. So I bought a 85mm 1.2 and did some shots. I first replicated the test I saw here, checking that the aperture does indeed change the shape of the circle of confusion, but how do we know that the full-open aperture is indeed as wide as it should have been? Well, I did a simple test, just shielding the lens contacts with some tape so the camera does not recognize it anymore. Result? Same brightness (even if I didn't shoot the images exactly at the same angles due to the fact that I had to move the camera to patch the lens), surely not the half EV drop that dxomark predicted.

Myth busted (at least with a 85mm 1.2, maybe I should try the 35 1.4 too just to be sure)

Note: that doesn't mean that indeed there is or could not be some light loss (albeit it would be easy to measure for your camera, just compare the image exposed to a given stop via shutter speed versus the same done by opening the aperture, on a taped lens), but that, at least for my camera, there seems to be no ISO cheating that I could detect.

Recipe for antialiasing as a post

I thought that I did post already this little experiment, but I didn't find it on the blog and I had to dig into my old sources... 

1) Identify edges. (From color? From normals and depth? In practice I've found the latter to be better)

2) Fit a primitive to edges, find parameters. A line? A line centered on the pixel? A curve? Most algorithms fit one of the first two. 
MLAA for example finds lines from the discrete edge detection, and the key of the algorithm is that is able to find lines even if they are nearly vertical (or horizontal). These lines have long steps when rasterized, and are hard to detect because you have to "look" way far from the pixel you're considering. MLAA uses pattern matching to achieve that, and that's also why it does not fit the GPU too well (at least DX9ish ones)
Simple edge detection is too local, won't know if a horizontal discontinuity is an horizontal line or part of a line at a nearly horizontal angle. Also it won't know how long that line is, so it won't know for how long the line approximation holds, in practice it will work decently only on curves, organic surfaces. This can be remedied by searching in a larger neighborhood, but it's not too simple and of course it costs performance...

3) Blend along the primitive. Either identify a "foreground" and "background" color and blend between the two using the coverage of the primitive on the pixel considered, or smooth by integrating (sampling) along the primitive. MLAA does the former, many post-filters do the latter (or a generic isotropic blur) to avoid computing the exact integral of the fitted line through the pixel.

Now how you do that defines your post-aa filter. MLAA is currently the most popular algorithm (especially on ps3, where you can use all these SPUs... there is a GPU version but it doesn't seem suited to run on the 360 GPU) and it seems to be almost the "only" choice nowadays but it's quite possible to do something decente even with more "conventional" filters. 

I started experimenting with this a while ago, to improve the PS3 2x quincunx filter resolve (that is commonly used "against" a 4x MSAA on 360 as PS3 is way slower to do MSAA). 
This idea of mixing MSAA and edge filtering is not new, this paper from ATI explores it and it's a very interesting read (also its citations, like this one, are a good inspiration)

It's important to be able to do this on the samples before the MSAA downscale because otherwise you'll loose information and it's harder to identify geometric discontinuities while preserving detail in the already antialiased (hopefully) interior shaded regions.

Also, as you're running your post effect on the full HD framebuffer, it's fundamental to be as fast as possible. With that in mind I started experimenting with the goal of doing the simplest filter that still looked good. This is what I've ended up with (beware, it's not shader code but Adobe Pixel Bender stuff):

void evaluatePixel()  {
float3 orig = sampleLinear(src, outCoord()).rgb;
        
float3 vb = sampleLinear(src, outCoord() + float2(1,0) ).rgb - sampleLinear(src, outCoord() + float2(-1,0) ).rgb;
float3 hb = sampleLinear(src, outCoord() + float2(0,1) ).rgb - sampleLinear(src, outCoord() + float2(0,-1) ).rgb;
float vg = dot(vb, float3(0.2126, 0.7152, 0.0722));
float hg = dot(hb, float3(0.2126, 0.7152, 0.0722));
        
float3 col = orig.rgb;
float2 off = float2(hg, -vg); float offl = length(off);
        
off/=offl;
col += sampleLinear(src, outCoord() + off).rgb + sampleLinear(src, outCoord() - off).rgb;
col/=float3(3,3,3);
float threshold = 0.25;
float blend = offl/threshold; if(blend>1.0) blend = 1.0;
dst.rgb = orig.rgb * (1.0 - blend) + col.rgb * blend; dst.a = 1.0;
}

The results are not too bad... As you can see MLAA is vastly better on straight, clean lines (see the bench) but it's actually a fair bit worse on curves/complex surfaces (see the leaves) and tends to mess/blur things that change often direction (see the metal rods on the left, above the zombie head). Maybe it's a matter of tuning, I used the original MLAA sourcecode from Intel.

Original image: Dead Rising 2 without MSAA


11 January, 2011

Code Tourism

Intro:
I've always liked the analogies between the art of computer programming and classical arts, many have been made by various authors but the most famous are surely the essays "Hackers and Painters" by Paul Graham and "The Cathedral and the Bazaar" by Raymond. 

And it's not about some sort of self-indulgent flattery, as being proficient in some scientific field is still seen as a less culturally valid than having technical expertise in one of the "classical" ones. No, the fact is that I really believe that coding is an amazingly creative process and that we are still really bad at it. We should learn more from the other creative arts, it's striking how badly "engineered" our process is. 
A painter gathers references (papers), draws studies (exploratory programming), then starts drawing (design), roughing in blocks and detailing areas (top-down coding). All this keeping a great control over his vision, and for most of the work he does... can we say that we do the same when coding our average tasks?

Now most of this has to do with the process itself, with our cumbersome workflow. It's harder for us to learn, to become proficient in these skills to the level that artists reach because our process is so far removed from our products. We don't interact with our creations, nor it's as-easy to visually assess their qualities.
I've wrote about this in some older posts, and I'm a strong advocate of live-coding and visualization techniques, but that's not what I wanted to write today (even if I already wrote quite a bit)...


Tourism:
Today I want to focus on another aspect, that is how we learn our art. How did you learn to program? I guess the story is the same for everyone, we probably started to read a book or study a language, then we went to do some exercises maybe, and we started to... program. Then more reading, more programming, maybe talking to other people, working together, sharing ideas.

All this is fine, but aren't we missing something? I mean, you might bet that artists share a similar education, maybe they learn about techniques, maybe they have some mentors or teachers, and they start drawing. True. But they also do another thing. They leverage on their history. They study the masters. Visit cities, look at the architecture, visit galleries, get inspired by other people's work, or by their surroundings.

I started thinking about this while reading "the ultimate code kata"; I bet when you started coding you did look at other people's source-code. Maybe got involved in a few projects, started tweaking stuff. Reading and understanding other people's ideas. But it's something that often we quickly dismiss after we get a bit more experienced.

Why? Well one of the reasons is that on average we think too highly of ourselves, but another is that is really a time consuming process. Starting to understand the code in a project can take quite some effort, and how can we know if there is anything interesting for us to look at anyway?

We need code galleries! We need tourist information offices, guided tours, sightseeing. If you are in charge of a opensource project, or so, you should think about this, maybe adding a page to your wiki with some "entry points" (for example, see this). 
Some projects are by themselves more "touristic", neatly made examples of great code (but also, as touristic cities tend to be, they can be less livable, like boost), some others contain great treasures, but they are hidden from the casual viewers (like my hometown Naples, that can be pretty hostile to tourists).

But this is not really only about opensource, I think it would be a great practice for a company too.
Usually one of the first things I do when I start working on a new project is to start understanding the main rendering flow, and usually there is no documentation about it, so I end up writing a wiki page with pointers to where to start, what functions are the main, most interesting ones, documenting a tour of the main "streets". 

But it could be more than that... why not having a "gallery" of links and short introductions to interesting bits of code and functionality in your project? People could be interested, and even start learning across disciplines. Same goes for "notable snippets" maybe they can come from code reviews, maybe the lead or the TD can write some notes when looking at the changelists...

So where do we start? If you have suggestions, send some links to files/functions in the comments!

06 January, 2011

OT: Owner of a Samsung Galaxy T959? In Canada?

Off topic, but it took me a bit to figure everything out and I hate, I hate, I hate having to tinker with technology (I love that I can, but I hate that I have to) so I'll post some tips if you, like me, did a cheap contract with Wind or Mobilicity, hated their phones and took the bad decision of buying an android based samsung galaxy from the US instead (only the US T-Mobile T959 will work with these carriers in canada).

The T959 officially only has Android 2.1 that sucks, so I've also ventured into the realms of firmware updating. Anyways, this is the to-do list.

1) Visit the xda-developers forums, they have all the info: http://forum.xda-developers.com/wiki/index.php?title=Samsung_Galaxy_S_SGH-T959

2) Root the phone (easiest way is to connect it to wifi and download this app: http://forum.xda-developers.com/showthread.php?t=746129 then reboot the phone into recovery mode and select "install packages").

3) Remove the carrier lock, it's not too hard. You'll need to download the android drivers, connect it with the USB cable and use ADB, that's a command-line android shell, let's you log into the phone from the PC. It involves doing some trickery with nv_data and generating some keys with a program, it will take a few commands (http://forum.xda-developers.com/showthread.php?t=822008&highlight=unlock)

4) Download the ROM Manager application and flash a good rom. I've found the team whiskey ones (http://www.teamwhiskey.com/DownVibrant.html) to be the best so far, it's a clean rom (no weird themes, no shit) and it's updated with the latest firmware and latest 2.2 modem (JL5). Update: Now the 2.2 is official from samsung. Still you can download the teamwhiskey version that comes with all sorts of tunings and most importantly the "voodoo" improvements (ext4, better display and audio) built in.
The modem is very important to have a decent data reception, it also affects battery use and GPS. You can even flash different modems on top of an existing firmware but I guess it's better to have a firmware that already includes the latest modem. 
Note that you might need to reboot into recovery and use the "install packages" option twice in order to have the rom manager recovery menu installed in the phone... Note also that the firmware .zip has to be moved into the "internal sd" can't stay into the external (transflash) storage. 
About "lagfixes": these appear to be hacks that let older kernels to use ext4 (I think) filesystem, thus making the phone quicker and removing lags. I'm not enabling these, if you do beware that if you flash a firmware that does not support these lagfixes the phone will not boot, as it won't recognize the FS. A flash with Odin, with the phone in download mode will be necessary then.

5) Condition your battery. Fully charge it and then let it fully discharge a few times, the phone will "record" the power levels and optimize the indicator. It's also advised to flash the new rom with the battery fully charged, otherwise the battery indicator will be wrong until you recondition.

6) If you screw up don't panic, chances are that you can still put your phone into download mode and use Odin to flash the stock samsung rom. Normally the ROM Manager is way better to flash stuff, use Odin only if the phone does not work anymore.

7) See this to set the phone parameters to work with Wind. Note that it might work even without touching the service mode settings, even it it might be convenient to lock it to the 1700 and 2100 bands only if you want to avoid roaming and have the phone lock on the "wind home" faster: http://forum.xda-developers.com/showthread.php?p=10241844

8) Fix your GPS. Better software settings here: http://gadgetwidgets.com/samsung-galaxy-s-gps-issue-fix-is-coming-soon-10092/ (you might need to use *#3214789650# instead of the published service number, also for me port 7275 seemed to work better).  Remember that the GPS might take a faily long time the first time you use it. There are a few GPS tester applications that are free on the android market. Also if your phone still does not work well you might consider this small hardware hack here: http://forum.xda-developers.com/showthread.php?t=878970

9) Next time buy an iPhone. Update: actually, even if the iPhone 4 is a nice phone and it will for sure stress you less, I have to admit, the Galaxy S/Android commuity is great!

Survive C++ / Collaborative guidelines experiment

Hi all! After many posts "against" C++ (and OOP, and design patterns), and after the very successful collaborative engine design experiment, I think it's the time for a new, more positive post.

In the end we're still tied to use C++ in our day to day jobs (well, if you do realtime rendering at least...) so we have to survive that...

Also I've always wanted to write some sort of coding "flashcards", something visual (also to help code reviews), of the form "if you see something like this, then you should think about that", so why not trying to do that, and also to leverage on the experience of you guys to make it super-awesome?

Here it comes... The collaborative visual coding guidelines experiment!


I will keep this etherpad around for a while. I hope it will see the same (or better!) participation of the last etherpad experiment I proposed. When the document grows "stable", I'll publish the results on the blog.

Enjoy!