"Many pictures turn out to be limp translations of the known world instead of vital objects which create an intrinsic world of their own. There is a vast difference between taking a picture and making a photograph." - Robert Heinecken

Priest: posted April 15, 2016 | 0 Comments



Clarifications: posted March 29, 2016 | 0 Comments



PS1KE: posted November 20, 2015 | 0 Comments

Just Wired That Way


real 13m18.280s

user 11m16.256s

sys 2m1.724s

Just Wired That Way: posted September 25, 2015 | 0 Comments

Neural Networks


Neural Networks: posted September 10, 2015 | 0 Comments posted August 03, 2013 | 0 Comments

A Missing Holiday

For random fun, here's a little one-day-only (Halloween) splash screen that I had made for a Rift internal build back in 2009 -- before it was called Rift. Ironically, it ended up that there was no build that day! So it was never used.

A Missing Holiday: posted December 26, 2012 | 0 Comments


turner_snow_storm _hannibal_and_his_army_crossing_the_alps.jpg

As " Senior Technical Artist" on Rift, my tasks often involved the creation of specialized tool software; helping non-technical people within the art dept (usually) solve specific problems; interfacing between the art, management, and engineering groups... But the part of my job that’s been most-visible to game players is shading.

The funny thing is that while shading is visible everywhere -- every pixel you see is a shaded one -- shading is a hidden art, like photographic lighting. It rarely has much of a narrative representational thrust of its own. You can make a drawing without shading, just as you can make a photo without any effort or thought about lighting. Yet you'll be hard pressed to find an un-shaded painting (or drawing) in a gallery or museum, just as you'll rarely see photos without very deliberate lighting in those venues, or in portrait or advertising studios; or especially in films, where the creators of those media have long learned and understood the value of careful control over tone, grading, and color. Not just on one costume or in one shot, but across the whole of their dramatic/artistic enterprise.

In computer image creation, shading -- the assignment of colors to pixels at all levels of detail -- is usually accomplished by the use of micro-programs called "shaders." In the case of Rift, I wrote nearly every shader, re-wrote those I didn't initially create, or created the shader-writing software that generated the shaders.

The exact meaning of "shader" can be a bit squirrelly for some. Engineers may prefer to call them "streaming processor functions" because they may not be "shading" visible images at all (see Mark Harris's excellent for some counter-examples). Most of the time, artists use the term "shader" and "material" interchangeably. The difference between a identically-colored materials that look like chalk, or ice, or plastic, or metal, or glowing ooze? The shader.

Shaders and interactions between shaders are also used to create lighting effects, glows, glints, shadows, depth buffers, and more. We'll talk about them as they come along in this series.

In the case of Rift, shaders for materials (and other purposes) not only had to look great for the best, high-end computers, they also had to be "heterofunctional": they needed to work on a wide variety of different PC's and in different environments. Some players had top-drawer computers with high-dollar GPU cards, while others had rather modest hand-me-down laptops. It was important to provide the best experience possible -- both pictorially and in terms of playable frame rate -- for all of these many thousands of players, across literally hundreds of material variations.

To complicate matters further, nearly all material shaders needed to have working analogues that run not only in the game as shipped, but also in our art-creation tools. This meant that each material needed its own OpenGL CgFX versions for use in Maya, custom preview modes for model building and animation, special DirectX versions for use in our modified Gamebryo 2.6 toolchain, some experiments with WebGL and Unity, and of course the various editions for player consumption at varying degrees of performance (at least two, sometimes up to five different versions).

As usual, the way to manage vast complexity is to bite off a little at a time and revise/polish as you go. I used to say (to steal a bit of a metaphor from.. Paul Graham? Not sure at this point, but we all steal from the best) that we started by jumping off a cliff and I built an airplane on the way down.


Shading: posted December 19, 2012 | 0 Comments

Rift's End: The Beginning


Four years ago I departed a good job at NVIDIA to join a start-up games company called Trion World Network -- Trion’s plan was to revolutionize online gaming in the US, and their stated goals were ones that I also shared: to create a new, innovative, more-immersive and immediate online-gaming experience.

I really believe that graphics matter. That great art is more than just simulating realism, and that it goes right to your emotions without waiting for rational analysis. That it’s those emotions that bring you back again and again to entertaining experiences, more than DPS and EXP and leveling-up to get the next BFG. Those are just background. Beautiful, vivid imagery -- even a beautiful image of an ugly subject -- goes right to the heart of an audience’s mind.

Among games, online ones had to that point been rather poor cousins in the graphics and art departments, with titles like Farmville and World of Warcraft. I’d had conversations with developers of other online games who declared “we don’t want to do anything more than Blizzard is doing” -- instead of seeing a future of ubiquitously-cheaper and more powerful machines for entertainment, they could only see that WoW had millions of subscribers & thought the only way to proceed was via a zero-sum  “WWWD?” -- “What Would WoW Do?” -- mindset.

Given the fact that game development cycles are now often longer than hardware-deployment cycles (a next generation of hardware may appear every year or so, while games to use that hardware take much longer), this vision gap was increasingly obvious. The future was being held back by a desire to simply repeat the successes of the past.

From my evangelist/consulting role at NVIDIA, it seemed like the shortest route to really show people what a beautiful online game experience might be like was not to advise the established developers, but to lead by doing: to simply go and create the future myself. And so I jumped, just hours before the stock market crash of 2008 got fully underway.

Two and a half years later, Rift: Planes of Telara opened to rave reviews; reviews that nearly always began with accolades about how great the game looked (Ten Ton Hammer: Graphics 95, “outstanding”; The Escapist: “One area where Rift definitely delivers is the graphics”; IGN: “an undeniably gorgeous game”; etc).

We continued to ramp it up for future revisions: so much so that previewers of  the first expansion set, Rift: Storm Legion, expressed their excitement about the “new renderer” (there was no new renderer, but I’d upgraded nearly all of the lighting and atmospherics code). When the expansion was released it received similar critical praise, such as this review from Gaming Trend: “[Storm Legion has] the best looking things in gaming, period, right now.

Quest Completed! You are dead.

However, the executives at Trion had a very different view. In December 2012, just a very few weeks after the release of Storm Legion, despite the superlative reception, they laid off a big chunk (most?) of the remaining Rift-focused art team: forty people including myself. If I were to speculate, the company seems to be backing away from “Triple-A” content focus and moving toward licensing deals with other production companies along with a focus on smaller, faster-iterating projects. Less “vision of the future of entertainment” and more same-ol’ game publishing. That’s just speculation on my part, but they’ve certainly reduced their ability to create top-shelf experiences like Rift in the short term future. Speculation.

While I’m not happy with the choices of management, I hope Rift continues to find an audience -- the whole point was to make something worth showing and sharing, a better gaming experience than what had been offered by anyone before. The effort means nothing if no one gets to experience the world we’ve created.

I’ve also decided to write a series here on some of the challenges and solutions in my process of collaboratively creating and tweaking the artwork and graphics for the game. While most of the art department has already been publicizing their work, as in this Polycount Art Dump, we were specifically forbidden from revealing “technical details.” Which means that if your work is nearly all technical details, well... you’re not allowed to talk about your work! Now I can. Watch this space.

Rift's End: The Beginning: posted December 15, 2012 | 1 Comments


One more for a Saturday -- see if you can push all the balls off-screen at once! (and no, it won't try to sell you car insurance)

Everything here, on the JS side, is set up using a shared array of initializer functions, just like the previous entry on that topic.

Next step might be to re-cast it as SVG... amazing that SVG seems really powerful, but compared to <canvas>, theres' almost no really good documentation...

791: posted May 05, 2012 | 0 Comments

HTML5 (& JQuery) vs Moveable Type, Part 2

Following up on the previous post, here are the details on a simple way to add multiple dynamic scripts to a Moveable Type index page.

Like the previous post, try using your mouse on this one! Can you slow down the particles?

Basically, we just need to add an (initially empty) array of function references to the page templates, which we'll use to capture each blog entry's unique scripts (rather than letting them launch themselves), and then iterate on that array for the entire page, once it's loaded and ready.

I'm using jquery, so I declare the array and my $(document).ready() function like so:

var gRActions = new Array(); // initially empty array of functions...

$(document).ready(function() {
  for (var a=0; a<gRActions.length; a++) {

Then in each blog entry, I write the same anonymous javascript function as I might write for $(document).ready(), but instead I just push it into gRActions:

gRActions.push(function() {

Now the page, regardless of how many blog entries it might contain, will include all of them in its page initialization. Remember also to make sure that any "global" javascript values (including function names!) in this entry, and all HTML elements like <canvas>, have unique names so that they won't collide with other blog entries, should they for some reason both be presented on the same HTML index page someday.

Also, as we've learned from the previous post: put some human-readbale text into the post before the scripting portion of the post, otherwise Facebook becomes confused.

HTML5 (& JQuery) vs Moveable Type, Part 2: posted May 04, 2012 | 0 Comments

HTML5 Canvas vs Moveable Type

With a little fiddling it's easy enough to use <CANVAS> (and jquery) in tandem with Botzilla's somewhat elderly (and modified) installation of Moveable Type.

Minor tricks:

  • Remember to suppress Text Formatting -- no automatic <P> tags
  • Between different blog entries, don't reuse variable names, or element names, if you think you might ever need to have multiple canvases on the same page (say, in index or search pages). You will disappear into the fourth circle of scoping hell.
  • Likewise, if you think that multiple canvases per page is a real possibility, then put each canvas's prep and render code into a distinct function, so that you can move your onload() or $(document.ready() functions into the header template, not the body of the entry itself. In the header, declare an initially-empty array of functions, and have your ready() function iterate through them.
    Then in each scripted entry, add your entry-specific render function(s) to that array. This way, the ready() function can just know what's needing to be set up for the specific page, regardless of which entries are being displayed and the # of visible canvases (A perusal of the initial state of this entry will show that I don't always follow my own advice. But adding that feature to Botzilla is one of my next steps). Be sure to put that array and calling function into all of your index and entry templates!
  • Linked sites like Facebook won't show <Canvas> or other animating elements, so if you want a good thumbnail, try adding a hidden image like so: <IMG SRC="/photo/journal//may03e-15.jpg" STYLE="display: none;" />
  • MT's preview page doesn't have all this extra js etc built-in. I suppose you can add it, and I probably will over time -- but as a quick workaround, to get a preview, I save my entry, press "Publish," then immediately look at the front index page -- if there's anything wrong, immediately change the entry state back to "Draft" and save again. This will remove the entry from the front page and the RSS feed, but: the "permalink" actual page file (in this case, "/blog/archives/000738.html") will still be there on the server! Download it and debug locally, then transport your changes back into MT. A bit of a shuffle but it's a workflow that can get you from points A to B.
  • Beware trying to test-post to Facebook, changing the contents of the blog entry (even for typos) and trying to post it to FB again -- FB caches everything the first time, so... if you want a change that will appear there, you need to make a new copy of your entire post, publish that, and hide the old one (how do I know this?).
  • Google+ is smart enough to recognize the difference between javascript blocks and actual human-readable body text. Facebook is not, and may just insert blocks of random code onto any FB link you create pointing to your entry. Maybe they will learn.

HTML5 Canvas vs Moveable Type: posted May 04, 2012 | 0 Comments

eReading, 2011 Edition


The pictures show a recent bargain toy -- a 7-inch Pandigital Novel eReader (aka "PDN," or "WPDN" to specify the white variant), re-flashed to expose its Android underpinnings and updated to Android 2.1 "Eclair." I managed to pick this one up during a recent clearance at the nearby chain store Kohl's for a tidy $59 (apparently, a few folks even managed to get a $20-off deal -- an Android tablet for $40!). Even at the more-usual price of $199 the Novel is no iPad, but at that price you could by three or four of them (or at the discount, a dozen or more!) for the price of a single iPad (Addendum: Apparently they sold 440,000 PDN's in 2010). So here's a quick review of my experience thus far:

Pandigital are known as much for their digital picture frames as for their e-Readers, and the Novel kind of feels less like a slowed-down computer and more like a turbocharged picture frame. This suits its designated purpose: as a full-color eReader. Not a game machine, or a media center, though in fact it's quite capable of playing YouTube videos or being a music player if the mood should strike you to use it that way. But really the CPU wasn't designed for rapid-fire screen updates. It's a device built around a slower, simpler, long-attention-span sort of experience.

I've got several different devices on hand for comparison, including current iPhone, iPad, a couple of new and old Android phones, and various other small computers, MIDs, readers, and so forth. Given this environment, these are the things that stand out about the Novel:

Resistive Screen
A good resistive screen, but it works best with the back-of-the-fingernail strokes rather than just the finger tips used on capacitive screens like the Nexus One or iPhone. This can throw you when moving back and forth between different devices.
Mentioned this before, but: it's okay. What I don't try to do is cram every possible use case into this device -- I am not expecting tons of animated bells and whistles or HD television or anything of that sort from it. This is one device among several, so I can let it just focus on what it does well. For my uses (more later), it's fine.
No Bluetooth
No Camera
No Phone or 3G/4G Connection
If I thought it was really important for me to record my face and location while typing my Engadget responses from the beach, I suppose these omissions would be truly upsetting. Happily, the simple wi-fi connection covers any of the locations where I'm actually likely to be using the PDN, and I can always turn on tethering from my phone if I'm desperate to update my apps while tooling along through traffic on US 101.
No Pentalobular Screws
Easy open, and easy tweak, too -- I doubled the internal memory by simply sliding open the case and swapping a hidden microSD card.
Long Battery Life
I've accidentally left mine on all day and it's still solid later on. It's a charge-daily device, though, unlike, say a Sony E-Ink reader (which can last for many days -- again, designed for intermittent bursts of activity, rather than continuous on-screen spinning and sparkling).
Standard SD Card Slot
The PDN can accept SD cards up to 32GB, though I haven't yet filled the free 4GB card I picked up at MicroCenter (There's also the hidden internal slot mentioned above, for microSD).
USB Port
The device has one, but it's really only useful for communication with other computers via ADB (Android Debug Bridge)
The Case
Not many choices compared to iPad, but I found this book-style folder at Bed Bath and Beyond, also on sale (The PDN is very much not the sort of device you'll find in usual computer stores -- everything has come from the Housewares Dept so far!).
Having the case makes a huge difference in the comfort level (one of the pix above shows it without the case for comparison). It's much easier to hold and I don't worry about banging-up the screen. This cover compares somewhat to the base cover for the smaller and lighter (but less capable & monochrome) Sony PRS-300 E-Ink reader.
The PDN is smaller and thicker than an iPad (which makes it feel heavy and dense, even though overall it's a bit lighter). I prefer this size, it suits my hand better, without being too small to read at a comfortable distance while reclining on the sofa (unlike the Sony, which needs the font size cranked up at that distance).

So what's it good for?

Principally, it's good for its chartered design tasks: reading eBooks and light web browsing. For these, it's excellent. By stripping-away the default Pandigital/Barnes&Noble skin (re-flashing doesn't delete these features, but simply makes them companion apps within the Android Home screen), the full range of Android apps can be seen and tried. I've found that the combination of wi-fi and Google books, Aldiko, & Kindle apps, along with Google Reader and the Skyfire browser, makes it more capable that any other reader save high-end tablets like the iPad or Galaxy Tab.

eReading, 2011 Edition: posted January 24, 2011 | 0 Comments

SpiceOfLife Update

Sometime it's hard to just let something be what it is, so I added a bunch of features to the Spice Of Life sketch. The OpenGL part is little changed, but the "built with Processing" part got expanded to make it simpler and self-explaining for users/players.

A nice thing about Processing is that sketches can usually be easily re-factored as web-browser applets. Having some issues with this one, sadly (and only on some computers), so I can't just post a playable applet on botzilla (yet).

Here's a video instead -- rather than a help screen, you'll see that SoL tries to guess what you're doing. This is a direct capture, though you can't see the mouse cursor.

Download (revised) file -- this is a zip of the entire sketch, ready-to-roll as a Processing project.

SpiceOfLife Update: posted October 16, 2010 | 2 Comments



A Processing sketch.

Download it here

SpiceOfLife: posted October 14, 2010 | 0 Comments


All content on is ©1994-2017 by Kevin Bjorke. All Rights Reserved.

Older Entries