Realtime Bump Mapping in Silverlight

Dec 6, 2009

Ah yes! Bump mapping is an effect that makes "plain" textures - such as stone wall, appear bumpy under a light.

Even for a 2D game, bump mapping has a lot of uses. For example, if you're building a space shooter, it would be 10000 times cooler if lights from explosions illuminate the ship, showing it's ridged surfaces.

I've seen the effect used in games in the main menu as well, where the light of the cursor illuminated a rough surface. This is what we're doing today:

Download Source Code

Notice how the light reflects properly off the bumpy surface as you move the mouse around.

I haven't optimized the effect (just a tiny bit Embarassed), but it still runs at 1024x768, with 3 lights on 1 CPU thread. You can add more (e.g with images of lightbugs) if you'd like or take it full screen - I think it can handle it!

I found a really good old tutorial on bump mapping while digging through my files today. It's from a person named Sqrt(-1) and unfortunately I didn't find his current website to point you there.

Anyway, here's another website that shows how to do this effect: http://tfpsly.free.fr/Docs/TomHammersley/bumpmap.htm

In my implementation the effect of the lights is limited to twice their radius, which pretty much gives the same effect as if you don't limit it. This reduces the effect's complexity to O(L1+L2+...LN) where Lx is the surface area of each light.

That's why you can scale large, especially with smaller lights. 

Edit: One possible optimization is to pre-calculate the normals for each x,y - this doubles the memory size for the bitmap but saves a lot of computations!

Hope you like it! Please comment!

  

Comments

12/6/2009 1:44:36 PM #

Rene Schulte

Hello Nikola,

great demo as always!
You might even get some more speed if you would implement the Bump mapping as a pixel shader, but you might soon encounter some limitations due to limited shader model 2 instruction count.

Rene Schulte | Reply

12/6/2009 2:00:16 PM #

Rene Schulte

FYI: I've just rembered that someone already did bump mapping in Silverlight 3 using a pixel shader:
blog.archetype-inc.com/.../bump-mapping-with-silverlight-3

Rene Schulte | Reply

12/6/2009 7:29:57 PM #

nokola

Thanks Rene!
The "manual" implementation is actually faster than pixel shader in this version of Silverlight (3).

I think that's because because the image gets converted from int to float on every frame, copied or something like that. Also the pixel shader runs on the CPU, which means all computations will be with float, which results in slower math operations Smile

nokola | Reply

12/7/2009 9:14:06 AM #

Rene Schulte

Have you tested it? It would be interesting to see a direct comparision.
I think the shaders are directly integrated in the Silverlight rasterization pipeline and that the buffer is not copied.
Have you seen my blog post where I compare serveral pre-WriteableBitmap techniques and also a shader:
"Silverlight 3 WriteableBitmap Performance Follow-Up"? kodierer.blogspot.com/.../...-writeablebitmap.html

Addionaly is the float and integer difference not that much on modern CPUs as it was in the past. I was quite surprised myself that the simple floating point DDA technique performed almost equal to the heavily optimized Bresenham DrawLine() algorithm that uses only simple integer operations.
kodierer.blogspot.com/.../...ines-silverlight.html

Rene Schulte | Reply

12/7/2009 8:22:40 PM #

nokola

I haven't tested it.
I tested other scenarios before, but was unconclusive  
You're right about the shaders - they should be in the pipeline and in direct apples-to-apples comparison are faster than their corresponding managed code. I got confused by something I was trying last week (getting image data back from pixel shader, which indeed copies it  

This said, I did a quick comparison of my bump mapping vs archetype's normal mapping (the one you mention above blog.archetype-inc.com/.../bump-mapping-with-silverlight-3 ). On 512x512 map, mine uses about 14% CPU vs about 18-20% CPU for theirs. To avoid changing my code to run on multiple threads (cores), I set MaxFrameRate to 20 to limit the pixel shaders to below 25% CPU - because my bump mapping is currently single-core and I'm running on quad-core CPU. I also changed my algorithm to pass the whole screen at once, with one light (similar to the pixel shader). If my code traverses the light area only, it uses about 5% CPU (we don't have similar/equivalent pixel shader to compare with though)

Normal mapping can be quite optimized with lookup tables and such and I believe performance can be brought very close (or the same) as my bump mapping algorithm. But then again, the pixel shader can be optimized too...

Another observation - with the managed code bump mapping, I can choose to precalculate only areas of the map that change: see the "foreach (LightMap map in LightMaps)" loop that calculates only pixels that are potentially "lighted up" as compared to the whole screen. This should be doable in the pixel shader as well (although not as straight forward)...

When I did the blur for the Living Noise demo (nokola.com/.../Faster-Living-Noise-2x-4x.aspx ), I couldn't find a pixel shader implementation that was faster for blurring on the CPU compared to mine...

I'm still not sure if I should be using pixels shaders vs managed code...probably making a managed code first (for the sake of simplicity/flexibility), then optimizing for pixel shader (if it's faster) would be the best choice.

nokola | Reply

12/8/2009 8:09:55 PM #

Rene Schulte

Just to make it clear. I wasn't saying that your implementation is slow or something. Indeed it's great! Smile 5 stars!

Rene Schulte | Reply

12/8/2009 11:12:18 PM #

nokola

Thanks, got it..I was just wondering how to make it faster, that's all. You're right that optimizing it for a pixel shader should be faster.

nokola | Reply

12/7/2009 9:27:50 AM #

pingback

Pingback from silverlightblog.cn

Realtime Bump Mapping in Silverlight Silverlight Blog

silverlightblog.cn | Reply

12/16/2009 8:15:52 PM #

Luigi

This is very cool!  Great performance and interesting technique.  

Our implementation [blog.archetype-inc.com/.../bump-mapping-with-silverlight-3] is definitely more proof of concept rather than an implementation for a full game.  Extending it to do multiple lights is possible but will definitely affect performance and you will hit the shader model 2 instruction limit at some point.  

However, you could pull off a large terrain area with many lights with some clever shader combinations (1 light version, 2 light, 3 light, etc), splitting the area into a grid (or even better a quadtree) to determine what shader to apply to which set of cells.  The only issue you'd run into is where there are more than 3/4 lights on a single cell.

Luigi | Reply

12/18/2009 11:35:28 PM #

nokola

Thanks Luigi!

Your implementation is pretty cool! I like that the light spans the whole surface...
I'm still figuring out what to do with the bump mapping - it seems like it would be nice to use for a space shooter. E.g. if something explodes close to the ship, it could "ligten in up", would be a nice subtle effect adding realism...Or the engine exhaust of the space ship can serve as a light source (should flicker too)...that would be nice Smile

nokola | Reply

12/19/2009 11:42:53 PM #

Luigi

There's definitely a lot of potential for game related uses!  

We used a modified version of our implementation for a holiday card we built this year, check it out at http://holidaycard.cloudapp.net.  It lets you cut, decorate, cook and share a gingerbread cookie.  The final product is bump mapped to make it look real.  You can then share it via email/facebook.  It was fun and interesting to generate the normal map dynamically based on the decorations and cut shape.

Luigi | Reply

12/21/2009 6:51:31 AM #

nokola

ah yes - pretty nice Smile I like the bumped up paint too!
offtopic random thought: I think we really need a common framework for "share on facebook" "send to friend", etc for Silverlight

nokola | Reply

12/21/2009 7:36:34 PM #

Luigi

The new version of the Facebook for Silverlight library was announced at PDC, it looked pretty comprehensive!

But yes a general "share" Silverlight content framework would be very cool.  We used the same format for the card as we did for pumpkin carver at http://halloween.cloudapp.net

Basically it just generates a unique url and then shares it with email or any other tools "social" tools.  We just added Facebook but abstracting the process so you can add Digg and others would be very cool.  I think the backend on Azure has been abstracted pretty well, we take any content from Silverlight and just write it to blob storage and give you back a unique identifier used to build the url to retrieve that content.  You can submit anything.  For the pumkin we did XML, for the holiday card it's a Zip with a bunch of files (color map, normal map, clip map, and an xml file for the message itself).

Luigi | Reply

5/20/2010 8:08:20 PM #

pingback

Pingback from 442.jordanbrandallamerican.com

1981 Datsun F10, F10 Diagram Cheap

442.jordanbrandallamerican.com | Reply

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading



nokola.com | Terms | Log in

Recent

About the author

Happy & enjoying life. Software enthusiast.
The opinions I express here and on nokola.com are mine and not my employeer's (Microsoft).
This is the official blog of nokola.com. You can find Silverlight samples, coding stuff, and hopefully other interesting things here.