8

I'm drawing into a DrawingContext, and I'd like to apply a drop shadow effect to part of the drawing. At the moment I create the relevant parts in a DrawingGroup and apply a BitmapEffect, but this has no effect:

var layer = new DrawingGroup();
using (var lcontext = layer.Open())
{
    // draw stuff in lcontext
}
layer.BitmapEffect = new DropShadowBitmapEffect { Color = Colors.Black, ShadowDepth = 3, Opacity = 0.5 };
context.DrawDrawing(layer);

This draws everything inside the layer correctly, but without the drop shadow effect.

What am I doing wrong / how else might I apply a drop shadow to a bunch of primitives in a DrawingContext?

LPL
  • 16,827
  • 6
  • 51
  • 95
Roman Starkov
  • 59,298
  • 38
  • 251
  • 324

2 Answers2

3

BitmapEffect is an old property (they used CPU-rendered effects) from pre .NET 3.5. The property has no effect in 4.0.

In 4.0 you should use Effect property, which uses Pixel Shaders.

DrawingGroup however doesn't appear to have an effect property - it sounds like you might need to set the effect on the parent UI element instead.

Paul Stovell
  • 32,377
  • 16
  • 80
  • 108
  • 1
    Hmm... I don't have a parent UI element; this `DrawingGroup` is rendered directly into a `RenderTargetBitmap`. Odd how I have to use UI elements for pure rendering, eh?... – Roman Starkov Dec 28 '11 at 16:25
  • 1
    I don't think it's odd - when creating a bitmap in memory, it hasn't been sent to the GPU, and so the GPU doesn't get to run the pixel shaders. The old `BitmapEffects` didn't use pixel shaders, they ran on the CPU, which is why they worked in this case. BitmapEffects were too slow most of the time though, which is why they are obsoleted. – Paul Stovell Dec 30 '11 at 15:07
  • In this situation you can probably use the drawing group to fill a Rectangle, and render the Rectangle to RenderTargetBitmap (don't forget to size the element first) - that should (I think) invoke the GPU to call your shader. – Paul Stovell Dec 30 '11 at 15:09
-2

If you're running on .NET Framework 3.5 SP1 or higher, you should use UIElement.Effect or Visual.VisualEffect (this one is protected so you would need to derive from it) instead, with an instance of System.Windows.Media.Effects.DropShadowEffect.

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • A `DrawingGroup` is neither a `Visual` nor a `UIElement`, so where do I apply that effect? – Roman Starkov Mar 07 '12 at 14:19
  • @romkyns - yes, because a DrawingGroup is a hierarchy/tree concept, not a "visual" concept. What do you put in your group? You must have something "visual" that will serve as the base for the drop shadow. – Simon Mourier Mar 07 '12 at 14:28
  • 1
    I draw stuff like images and primitives into my `DrawingGroup` (using code I quoted in the question). I then render it using `DrawDrawing`. I’d like to do the same, but have everything inside the `DrawingGroup` to cast a shadow. – Roman Starkov Mar 07 '12 at 14:40
  • @romkyns - well, the Drawing classes hierarchy is probably not the good horse to ride when you want to use builtin (fast) drop down shadows. You'll have to use the Visual/UIElement classes hierarchy. WPF is mostly a composition engine where you build your UI hierarchy (probably using a holding Canvas) and let the system do the rendering job. – Simon Mourier Mar 07 '12 at 16:19
  • 1
    `DrawingContext` is a perfectly capable replacement for the GDI APIs, in my experience. There just doesn’t seem to be a ready-made drop-shadow effect, which is understandable. Would you like to update or remove your answer? As it stands, it’s inapplicable/misleading. – Roman Starkov Mar 07 '12 at 17:40
  • 2
    let me give u my angle - i've inherited SomeControl from FrameworkElement, and overriden OnRender. UIElement.Effect is just not good enough- it puts the effect on the entire element, whereas the depricated PushEffect could put the effect only on a few drawingContext.DrawXXX lines, allowing me not to put the effect on the entire element at once. WPF4 => less control than WPF3? – Elad Katz Mar 07 '12 at 21:23
  • @romkyns - I will certainly not remove my answer. I spent some time trying to help, I will not spent points to remove it. – Simon Mourier Mar 08 '12 at 08:08
  • 1
    @SimonMourier I appreciate your efforts to help. FWIW, I don’t think it costs anything to delete an answer. – Roman Starkov Mar 08 '12 at 11:03
  • @EladKatz Did you figure out a solution to this problem. I want to have shadows on individual items I draw using drawingContext.DrawXYZ – AmaltasCoder Mar 23 '12 at 12:11
  • @AmaltasCoder nope. i came to think that this is impossible with WPF4. – Elad Katz Mar 23 '12 at 21:42