Friday, December 31, 2010

3D in Silverlight part 4: spherical image mapping

Spherical image mapping is a technique to wrap a 2D image around a 3D sphere. In my little ray tracer, I apply this technique to create an earth-like object.



The same technique is used to wrap the image around a cube which gives an interesting effect.

Live version:

[It might take some time until this Silverlight application is loaded so please be patient. If you're viewing this post in an RSS reader (such as Google Reader), you might have to open it in your browser.]

Happy 2011!

Friday, December 24, 2010

3D in Silverlight part 3: planar texture mapping

A quick update before the holidays: the ray tracer now also supports planar texture mapping. This was actually very simple to implement, the most difficult part turned out to be to load the bitmap in memory. In the example below I've used a free texture that was downloaded here.



Live version:

[It might take some time until this Silverlight application is loaded so please be patient. If you're viewing this post in an RSS reader (such as Google Reader), you might have to open it in your browser.]

Happy holidays!

Silverlight: loading a WriteableBitmap from file

I’ve just spent quite some time trying to do something that seems very simple: embedding an image in a Silverlight application and loading this image into a WriteableBitmap (because I need to read the values of the individual pixels).

My first attempt was to add the image to my project as a resource and use the following code:

Uri uri = new Uri("Images/Texture.jpg", UriKind.Relative);
BitmapImage imageSource = new BitmapImage(uri);
WriteableBitmap bitmap = new WriteableBitmap(imageSource);  // EXCEPTION

However, an exception is thrown on the last line. Luckily the internet came to the rescue, and these two great site suggest basically the same solution:

  • Using BitmapCreateOptions.None to make sure the bitmap begins to load immediately.
  • Subscribing to events to know when the image has actually loaded.

However the proposed solution did not work in my case because the image fails to load with an AG_E_NETWORK_ERROR error.

In the end I took a different approach: I load the resource using Application.GetResourceStream so I’m sure that the data is completely loaded before it is handed to the WriteableBitmap. This is the code:

StreamResourceInfo sri = Application.GetResourceStream(new Uri("Images/Texture.jpg", UriKind.Relative));
BitmapImage src = new BitmapImage();
WriteableBitmap image = new WriteableBitmap(src);

In my case it has the advantage of being synchronous which makes the overall code much simpler (but I understand that asynchronous behavior may often be better in a web-context).

When adding your image to your Silverlight project, the build action should be set to ‘Content’ instead of ‘Resource’. This means that the image will not be included in the dll, but it will be stored in the xap-file. You can check this by renaming the xap-file to zip and looking at the content.

So there are some non-intuitive steps involved when trying to accomplish this simple task. Hopefully this post can be helpful if someone else has this problem.

Saturday, December 18, 2010

3D in Silverlight part 2: the cube

I’ve added support for cubes to my ray tracing code. This is a screenshot for those who do not whish to install the Silverlight plugin:


The code still runs at about 20 fps on my PC (which is just acceptable). You can check it out yourself:

[It might take some time until this Silverlight application is loaded so please be patient. If you’re viewing this post in an RSS reader (such as Google Reader), you might have to open it in your browser.]

Wednesday, November 24, 2010

Real-time ray tracing in Silverlight

I’ve always been very interested in computer generated graphics. A technology that I find particularly interesting is ray tracing. This technique is based on the physical interaction between light and materials, and it can be used to generate very realistic images.

Because of the physical accuracy, this technique is very suited to predict how something will look before it’s even built. When we were in the process of building our home, I created several ray-traced images that we used to choose the color of the bricks, the windows, the roof, … This way it was possible to create virtual versions of our future home and select the one that most matched our taste. This is such a ray traced image that I created:


Developing a ray tracer is not very difficult and through the years I’ve written some simple ray tracers. Unfortunately the calculations are very CPU-intensive. That is the reason why 3D games use different techniques which are also nice to look at but they are not physically accurate. But computers are getting faster and faster, so real-time ray tracing will likely become feasible in the near future.

As a test-case, I’ve optimized my old ray-tracing code and I’ve managed to get it to run at real-time speed. Check out this Silverlight version:

[It might take some time until this Silverlight application is loaded so please be patient. If you’re viewing this post in an RSS reader (such as Google Reader), you might have to open it in your browser.]

Note that you need a fairly fast CPU to get it to run real-time (on my quad-core it runs at 20 frames per second). You don’t need a fancy graphics card because this ray tracer only uses the CPU. The implementation is fairly straightforward, no real tricks have been used to improve the performance (other than common sense). I believe that, given enough effort, it would be possible to improve the performance considerably. That would allow it to render a more complex scene real-time.

Sunday, November 21, 2010

Oldskool demo effect in Silverlight: plasma

Just like last week, I’ve tried to recreate a demo-effect in Silverlight. This time I chose the plasma-effect which was very popular (it can be seen for instance in the classic State of the Art demo).

Actually this effect is much easier to implement than the twister of last week. I’m not the first one to implement it in Silverlight: other versions can be found here and here. Example code can be found here and here (but I used another variant).

[I’ve noticed that it might take some time until the Silverlight application is loaded, so please be patient. If you’re reading this in an RSS reader (such as Google Reader) you will have to open this post in your browser to see the effect.]

Wednesday, November 17, 2010

Oldskool demo effect in Silverlight: the twister

As a kid, I was really fond of those oldskool demos on the Commodore 64 and the Commodore Amiga (but of course back then they weren't called oldskool). For those of you who have no idea what I'm taking about, you can watch most of these demos on youtube these days (such as here). Remember that these were created on hardware that is really ancient compared to nowadays.

These demos are created by programmers and artists with only one purpose: to impress other programmers and artists. In many aspects they resemble magician's tricks: they seem very impressive on the surface but underneath they use all kinds of tricks to make this possible. For instance, many 3D effects in demos were not really 3D at all. The tricks involved were kept very secret, but if an effect was very impressive, many other demo programmers would try to replicate and improve it (as is the case with magician's tricks).

I've recreated one of these effects in Silverlight. As a bonus I've added anti-aliasing and soft shadows (which weren't common in the old days). In the tradition of the oldskool demos I won't say how this was done, but maybe you can figure it out?


[If you're reading this post through an RSS reader (such as Google Reader), you might have to open the post in a separate window of your browser to see the effect.]

Friday, December 05, 2008

Saving and restoring GDI+ state

When you create complex drawing code, you probably will split this over multiple methods and pass the Graphics-object between these methods. But because the Graphics-object contains state, all changes that you apply in a method will be propagated to the other methods as well. Often this is not what you want.

The common way to work around this is to reset all the changes that you made at the end of the method:

   1: void PaintBackGround(Graphics g)
   2: {
   3:     SmoothingMode oldSmoothingMode = g.SmoothingMode;
   4:     try
   5:     {
   6:         g.SmoothingMode = SmoothingMode.AntiAlias;
   7:         ...
   8:     }
   9:     finally
  10:     {
  11:         g.SmoothingMode = oldSmoothingMode;
  12:     }
  13: }

But if your code changes a lot of properties this will become cumbersome. In these cases it is simpler to save and restore the entire Graphics-state like this:

   1: void PaintBackGround(Graphics g)
   2: {
   3:     GraphicsState oldState = g.Save();
   4:     try
   5:     {
   6:         g.SmoothingMode = SmoothingMode.AntiAlias;
   7:         ...
   8:     }
   9:     finally
  10:     {
  11:         g.Restore(oldState);
  12:     }
  13: }

Wednesday, November 26, 2008

Creating a single-instance application

A lot has been written on the internet on how to create a single-instance application in C#. The proposed implementations fall into three categories:

  • Check if a process with the same name is already running (using GetProcessesByName). This is plain wrong because it needs administrator privileges. Furthermore it will not work if there is another process that happens to have the same name as your process.
  • Using the Microsoft.VisualBasic namespace (as explained here). This probably works OK (I have never done this), but it feels a bit wrong. Note that this approach is promoted in the book ‘Windows Forms 2.0 Programming’.
  • Using a Mutex.

Personally I think that the last approach is best, but there are some details that you need to get correct if you want to rely on this. This is the pattern that I propose:

   1: static class Program
   2: {
   3:     static Mutex s_Mutex;
   5:     /// <summary>
   6:     /// The main entry point for the application.
   7:     /// </summary>
   8:     [STAThread]
   9:     static void Main()
  10:     {
  11:         bool instantiated;
  12:         // WARNING: you need to replace the GUID in this string!
  13:         s_Mutex = new Mutex(false, "Local\\MyAppName{A6F214AB-669D-41B2-9F30-8DD5E5AC9AE1}", out instantiated);
  14:         if (!instantiated)
  15:         {
  16:             MessageBox.Show("The application is already running");
  17:             return;
  18:         }
  20:         Application.EnableVisualStyles();
  21:         Application.SetCompatibleTextRenderingDefault(false);
  22:         Application.Run(new Form1());
  23:     }
  24: }

The pattern is applied to a Winforms application, but of course it can be applied to any type of application.

For those who don’t know what a mutex is: it is a Windows kernel-object that can be used for synchronization between threads and processes. The proposed pattern tries to create a mutex with a certain name and checks if this mutex already existed. If it did, this means that our process was already started.

Here are the details that are important:

  • The mutex must be declared static, because we have to make sure that the garbage collector will never dispose it.
  • The name of the mutex should contain a GUID, which ensures that no other application uses the same name. If you don’t know how to create a GUID, click here.
  • The mutex is local, which means that every user that is logged on can create his own instance. If you don’t want this, simply ommit the ‘Local\\’.
  • The mutex contains the name of the application. As a general guideline, I think that named kernel objects should have a descriptive name. This makes it easier when debugging problems: using tools such as SysInternal’s WinObj, you can look at the state of all the kernel objects. If your object has a proper name this will be much simpler.

Wednesday, November 19, 2008

GDI+ objects should be disposed

When a Winforms-control needs to do custom painting, this is typically done by overriding the OnPaint-method like this:

   1: protected override void OnPaint(PaintEventArgs e)
   2: {
   3:     base.OnPaint(e);
   5:     Graphics g = e.Graphics;
   7:     // WARNING: this code should be avoided because it does not dispose the GDI+ objects
   8:     g.FillRectangle(new SolidBrush(Color.Black), this.ClientRectangle);
   9:     TextRenderer.DrawText(g, "Hello world!", new Font(FontFamily.GenericSansSerif, 10f), new Point(10, 10), Color.White);
  10:     g.DrawLine(new Pen(Color.White), new Point(0, 0), new Point(100,100));
  11: }

On the internet you will find lots of example code that does custom drawing like this. The problem is that every time this code is executed (and in GUI this can be a lot!), a bunch of GDI+ objects are created that are not disposed. Eventually the garbage collector will kick in and will dispose all these objects. This is to be avoided however:

  • This puts a lot of stress on the garbage collector.
  • These objects will be cleaned up in two fazes which will impact performance even more.
  • GDI+ handles are limited resources, but the garbage collector is only invoked if your application needs more memory. It is not unlikely that your code uses a lot of GDI+ handles but does not consume a lot of memory. This may mean that the garbage collector never executes, and your code may consume a huge amount of GDI+ handles.
    This issue was especially problematic before GC.AddMemoryPressure() was added in .NET 2.

The obvious solution is to dispose the GDI+ objects when they are not needed anymore:

   1: protected override void OnPaint(PaintEventArgs e)
   2: {
   3:     base.OnPaint(e);
   5:     Graphics g = e.Graphics;
   7:     // Much better: less stress on the garbage collector
   8:     using (SolidBrush brush = new SolidBrush(Color.Black))
   9:     using (Font font = new Font(FontFamily.GenericSansSerif, 10f))
  10:     using (Pen pen = new Pen(Color.White))
  11:     {
  12:         g.FillRectangle(brush, this.ClientRectangle);
  13:         TextRenderer.DrawText(g, "Hello world!", font, new Point(10, 10), Color.White);
  14:         g.DrawLine(pen, new Point(0, 0), new Point(100,100));
  15:     }
  16: }

This code is good but we can make it even better. Note that every time the code is executed, new GDI+ objects are created and disposed. In this particular case this is a waste because the objects will be identical every time. It would be better to create the objects only once, and reuse them every time.

It seems that the Winforms-designers at Microsoft also had this idea, because they already cache the commonly used brushes and pens in the Brushes and Pens classes. For the Font-object we need to do this ourselves:

   1: static readonly Font s_Font = new Font(FontFamily.GenericSansSerif, 10f);
   3: protected override void OnPaint(PaintEventArgs e)
   4: {
   5:     base.OnPaint(e);
   7:     Graphics g = e.Graphics;
   9:     g.FillRectangle(Brushes.Black, this.ClientRectangle);
  10:     TextRenderer.DrawText(g, "Hello world!", s_Font, new Point(10, 10), Color.White);
  11:     g.DrawLine(Pens.White, new Point(0, 0), new Point(100,100));
  12: }

Notice that our Font-instance is declared as static because it can be reused when there are many instances of our control.

Of course this technique can only be used if the GDI+ objects are the same every time. If they are highly dynamic then you will have to create a new object every time (this may occur if you are drawing a part of an animation). But don’t forget to dispose these objects with the using-statement.