6
\$\begingroup\$

Diablo 2 is a game with isometric graphics. However, unlike other isometric games, D2 has the option to activate perspective. Obviously, the D2 developers found a clever trick to convincingly fake perspective in their isometric engine. It has to be a fake, because D2's graphics assets consist of pre-rendered isometric 2D tiles.

I want to implement a similar effect in my isometric graphics engine, but was unable to find out how to deal with the more subtle issues of applying perspective. A similar question has been asked on this site before. Unfortunately, the answer to that question does not help with the specific problems I am facing.

Let me explain my approach in detail. I use two dimensional tiles for floor and walls that look like this: 2D Graphic Tiles (Note that the floor tile is not actually part of the wall tiles. I added it just for clarity.)

These tiles can be assembled in 2D to create an isometric scene:Isometric View

It is actually pretty easy to fake perspective in such an isometric scene. Slightly enlarging objects at the bottom of the screen and shrinking objects at the top makes them seem close or distant, and creates a subtle illusion of perspective. This is easily achieved in a vertex shader and works very well for floor tiles: Fake Perspective. The floor looks good, but the walls do not. Vertical lines get distorted. I can fix this by applying uniform scaling to objects, instead of distorting them like floor tiles. The scale factor depends on the object's y-position. This works well for character sprites and front facing walls, but fails for diagonal walls and more complex objects.

Now the actual question: enter image description here A front facing wall can be scaled by the y-coordinate of points A and B, which is the same. However, this does not work for corners or diagonal walls where the points have different y-coordinates. It seems, for an accurate perspective effect, each wall tile needs to be treated differently so they can fit seamlessly together. This does not seem feasible to me. Ideally, I want to treat all wall tiles equally.

Is it possible to scale wall tiles so they fulfill the following criteria?

  • they should become continuously smaller the further up on the screen they are
  • they should not appear to move or jitter when the viewpoint changes
  • they should seamlessly fit together

Any help is appreciated. I've been worrying about this for days, but maybe I'm thinking too complicated :)

update: enter image description here Isometric view with increasing perspective. Note what happens when wall tiles are simply scaled. This works well for front facing walls only.

I want to approximate perspective correction so that all wall tiles fit seamlessly.

\$\endgroup\$
  • 1
    \$\begingroup\$ Thank you for adding so many helpful illustrations to your question. But your question would benefit even more from a screenshots from Diablo 2 which shows the effect so it becomes more obvious what effect you want to reach. \$\endgroup\$ – Philipp Dec 13 '14 at 17:24
  • \$\begingroup\$ just an idea, but why don't use a full 3d engine for rendering your isometric view? \$\endgroup\$ – Ali1S232 Dec 13 '14 at 17:43
  • \$\begingroup\$ @Philipp that is because I don't have Diablo 2 available at the moment, but I'll see what i can do. \$\endgroup\$ – kazemakase Dec 13 '14 at 20:54
  • 1
    \$\begingroup\$ Just an idea, but you can provide your shader with another texture, representing the height of that pixel, and take that information into account \$\endgroup\$ – Ali1S232 Dec 13 '14 at 22:24
  • 1
    \$\begingroup\$ There was an in-depth article dissecting D2 render on the web. (simonschreibt.de/gat/dont-starve-diablo-parallax-7) \$\endgroup\$ – Kromster Jan 27 '16 at 13:57
2
\$\begingroup\$

I want to thank everyone who took their time to respond to my question. I finally came up with my own solution, which nevertheless was inspired by the suggestions here.

Especially this comment from Ali.S turned out to be particularly useful:

Just an idea, but you can provide your shader with another texture, representing the height of that pixel, and take that information into account – Ali.S Dec 13 at 22:24

Instead of using another texture with height information, I went for an approximate approach. I store for each tile a line that passes through the two ends of the wall at ground height:

enter image description here

Now it is possible to scale the two sides of each tile differently, according to the y-coordinate of the line's endpoints. However, in case of the corner tile, this leads to distortions because the wall does not exactly coincide with the line.

enter image description here

Fortunately, these distortions are not a big problem since I only plan to apply a subtle perspective effect. This makes the distortions hardly noticeable, unlike in the image above, where perspective is highly exaggerated for illustrative purposes.

\$\endgroup\$
0
\$\begingroup\$

I would try using a screen buffer to draw all the walls (and possibly the characters) to. And then you can apply the perspective to all the walls at once. This should eliminate any errors you are getting because perspective is being applied to a single image rather than multiple images. You would than assemble the scene by drawing floor layer and then the wall layer on top of it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.