3
\$\begingroup\$

I have like hunderd of isometric objects. One example:

Elf building

I'm trying to find a way to automate creation of shadow they're casting. I ended up with following transformation:

   matrix.Shear(-0.25f, -0.25f, MatrixOrder.Append);
   matrix.Translate(0.5f * source.Width, 0.125f * source.Height, MatrixOrder.Append);

Whole algorithm:

  string sourceFileName = @"c:\in.png";
  string targetFileName = @"c:\out.png";
  using (var source = (Bitmap)Bitmap.FromFile(sourceFileName)) {
    using (Bitmap target = new Bitmap(source.Width * 2, source.Height, PixelFormat.Format32bppArgb)) {
      using (var g = Graphics.FromImage(target)) {
        GraphicsPath gp = new GraphicsPath();
        gp.AddPolygon(new Point[] { new Point(0, 0), new Point(source.Width, 0), new Point(0, source.Height) });
        var matrix = new Matrix();
        matrix.Reset();
        matrix.Shear(-0.25f, -0.25f, MatrixOrder.Append);
        matrix.Translate(0.5f * source.Width, 0.125f * source.Height, MatrixOrder.Append);
        gp.Transform(matrix);
        g.DrawImage(source, gp.PathPoints);
      }
      var grayscale = new Bitmap(target.Width, target.Height, PixelFormat.Format32bppArgb);
      for (var x = 0; x < target.Width; x++) {
        for (var y = 0; y < target.Height; y++) {
          var pixel = target.GetPixel(x, y);
          if (pixel.A != 0) {
            pixel = Color.FromArgb(255 / 3, Color.Black);
          }
          grayscale.SetPixel(x, y, pixel);
        }
      }
      for (var x = 0; x < source.Width / 2; x++) {
        for (var y = source.Height - 1; y >= 0; y--) {
          var pixel = source.GetPixel(x, y);
          if (pixel.A != 0) {
            break;
          } else {
            grayscale.SetPixel(x, y, Color.FromArgb(0, 0, 0, 0));
          }
        }
      }

      grayscale.Save(targetFileName, ImageFormat.Png);
    }
  }    

Which produces something like:

Shadow

It kind of works - but not 100% - the angle of shadow is changed according to proportion of the source object. Is there a way or algorithm that will work 100% or be closer to real ?

Elven village

(Edited to explain more detaily).

\$\endgroup\$
4
  • \$\begingroup\$ +1 this is seriously awesome. Try messing around with Photoshop first to see if you can get something useful, and then apply it to code. \$\endgroup\$
    – ashes999
    Aug 7 '13 at 22:20
  • \$\begingroup\$ If you explain specifically what's "not 100%" with it, you're likely to get answers that are more relevant to you. Since this appears to be a stylistic thing, it's going to be difficult for people to answer you without a detailed technical description of exactly what you're looking for. \$\endgroup\$
    – House
    Aug 7 '13 at 22:40
  • 1
    \$\begingroup\$ Agreed with Byte56 - we need more explanation of how your current approach is failing / what you're looking for. Some screenshots of bad cases (especially in context in the game, not just isolated tiles) might help. \$\endgroup\$ Aug 7 '13 at 22:53
  • \$\begingroup\$ Why do you translate it? Just a shear without translation gives more realistic result in my opinion when aligned from the bottom of the images. \$\endgroup\$
    – msell
    Aug 8 '13 at 7:25
3
\$\begingroup\$

There is absolutely no way of making it perfect because you simply don't have enough information about depth. You have 2D representations of 3D objects.

Think about this. If it were a real object, there would be parts of it that the camera can't see, but still block the light and cast a shadow. Also, think about each pixel, there is no way to know how high off the ground the surface at that pixel is. I mean, WE can see that steps are leading up to a treehouse, but an algorithm does not have that kind of semantic information, it just sees a 2D sheet of colours and alphas.

I think what you have is the best approach you can hope for. Although, like ashes999 suggested, you can use photoshop to tweak your projection/angle/pivot.

Also, you could accumulate some jittered samples to get an antialiased shadow which would look nicer.

As for the angle being dependent on proportions, I am not sure what kind of linear algebra system you are using, but you could experiment with making the shear inversely proportional to sprite proportions to counteract the effect. I'll leave it up to you to experiment.

\$\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.