I was reading through an excerpt of a speech from Jeff Strain. I've read the speech many times before throughout my career -- it was given in 2007 -- but reading it nearly a decade later I found myself unsure of the words being said.
Here's the excerpt:
"Before you start building the ultimate MMO, you should accept that “MMO” is a technology, not a game design. It still feels like many MMOs are trying to build on the fundamental designs established by UO and EQ in the late ’90s. In the heyday of Doom and Quake we all eventually realized that “3D” was a technology, distinct from the “FPS,” which was a game design. It’s time we accepted that for MMOs as well. We are finding ways to overcome many of the limitations of the technology that dictated the early MMO design, such as Internet latency and limited global scalability. These improvements can enable a new class of online games that break out of the traditional MMO mold and explore new territory. It can be a daunting proposition to willfully walk away from what seems to be a “sure thing” in game design, but lack of differentiation is probably the number one reason that MMOs fail, so we all need to leave the comfort zone and start innovating, or risk creating yet another “me too” MMO."
The speech is somewhat prophetic at the end, saying "me too" mmos are likely to fail.
What's interesting is that 9 years later we've seen a lot of new types of MMOs. Survival MMOs, the MMORTS, social oriented online games. Even strictly non-combat MMOs like Ever Jane. The list goes on. But at the same time, we've still seen a lot of "Me Too" MMOS. Many have failed, but a fair number of them have succeeded. Perhaps most strangely is the fact that Guild Wars 2, the successor to Guild Wars and made by the company co-founded by Jeff Strain is very much a "Me Too" MMO that is succeeding. When Guild Wars 2 was first presented to the Guild Wars community, it was even pitched as "an MMO more like what you think a typical MMO is like" (paraphrasing here). The most notable difference is the persistent explorable zones. And while the dynamic events are an attempt at innovation, it's more of an evolution (Quests -> Group Quest -> Warhammer Online's Public Quests -> Guild Wars 2's Dynamic Events). Hearts are especially quest-like in their lack of real impact on the world your character lives in.
Now, by my second-hand hearing, Guild Wars 2 has been much more successful than Guild Wars 1 was from a monetary standpoint. I don't know if that's because of the more traditional design (granted, with plenty of non-traditional mechanics thrown in the mix) or a result of something else. Either way, I'm reading these words differently today than I was the last time I set eyes on them.
Friday, January 29, 2016
Saturday, January 16, 2016
Blending Pixels
A task at work has recently required me to do some graphics stuff. I'll be the first to admit that as a learned discipline I'm not a graphics programmer. I enjoy almost any kind of programming and in my hobby work I find graphics programming especially fun. But simple things in that realm of the programming world I am embarrassingly ignorant of. Even something like... blending two pixels.
But! That wasn't going to stop me from researching and validating the right way to alpha blend two pixels together.
Now in reality, the task isn't so much for pixels, but rather for heightfield data. Now often heightfield data is just a single-channel pixel anyway, but in our engine heights are represented as floats. To expand the feature set of our terrain engine, our heightfield data needed to be modified to include layers and an alpha channel. So each heightfield sample is now two channels -- height and alpha.
Of course, googling and grabbing an algorithm isn't all there was to it. I wasn't really going to be satisfied with the answers I found unless I could test it myself. Sure, I could plug the code in and see what results I get, but it was much faster to throw up my favorite web app -- Desmos Graphing Calculator.
Compared to my last documented use of Desmos, this is absurdly straightforward. I'm visualizing the alpha channel along the x axis and the height channel along the y axis. I'll admit, It's a bit disorienting until you get used to it. Regardless, a/h3 is the resulting value. a/h1 and a/h2 are the inputs. Alpha values are normalized, so we're working with ranges between 0 and 1.
The formula for the output ends up looking like this in code. As usual this code is for illustrating the formula -- not for being performant code.
But! That wasn't going to stop me from researching and validating the right way to alpha blend two pixels together.
Now in reality, the task isn't so much for pixels, but rather for heightfield data. Now often heightfield data is just a single-channel pixel anyway, but in our engine heights are represented as floats. To expand the feature set of our terrain engine, our heightfield data needed to be modified to include layers and an alpha channel. So each heightfield sample is now two channels -- height and alpha.
Of course, googling and grabbing an algorithm isn't all there was to it. I wasn't really going to be satisfied with the answers I found unless I could test it myself. Sure, I could plug the code in and see what results I get, but it was much faster to throw up my favorite web app -- Desmos Graphing Calculator.
Compared to my last documented use of Desmos, this is absurdly straightforward. I'm visualizing the alpha channel along the x axis and the height channel along the y axis. I'll admit, It's a bit disorienting until you get used to it. Regardless, a/h3 is the resulting value. a/h1 and a/h2 are the inputs. Alpha values are normalized, so we're working with ranges between 0 and 1.
The formula for the output ends up looking like this in code. As usual this code is for illustrating the formula -- not for being performant code.
struct HeightSample { float height, alpha; } void Blend(HeightSample& out, const HeightSample& a, const HeightSample& b) { out.height = a.alpha * a.height + b.alpha * (1.0f - a.alpha) * b.height; out.alpha = a.alpha + ((1.0f - a.alpha) * b.alpha); }It's interesting to note that while the alpha blending is a commutative operation (that is, if you swap the input values, the output is the same), the same it not true of the height channel. This is because sample
const HeightSample& a
is considered the "top" pixel. They are not even commutative if both alpha values are 0.5. This isn't particularly intuitive, so I thought it was worth mentioning.
Subscribe to:
Posts (Atom)