Draw Shadows using DisplayPipeline.PostDrawObjects()

Hello,

When an object is added to Document, shadows are displayed in Rendered and Raytraced Display Modes, although when it’s drawn like that:

  DisplayPipeline.PostDrawObjects += PostDrawObjects;
  private void PostDrawObjects(object sender, DrawEventArgs e)
  {
        e.Display.DrawMeshShaded(meshToDraw,displayMaterial);
        e.Display.DrawBrepShaded(brepToDraw,displayMaterial);
   }

There are no shadows, it happens using PostDraw, DrawOverlay and DrawForeground


Is there a way to enable the shadows using these methods (DrawMeshShaded and DrawBrepShaded)?

Thanks.

@jeff, can you assist?

Hey Harper,

The “shadow pass” is always/only done in the middle ground channel… which is where any/all object drawing is supposed to take place. If you’re drawing objects in any other channels, and those objects are supposed to be part of the “primary” frame buffer output, then all bets are off as to whether or not those objects are going to participate and/or produce the expected results.

You cannot just call some draw method at any point, at any time within the pipeline’s channel chain, and then expect it to work or produce the correct results…There are very specific things that happen at very specific times within the pipeline…and they’re done for very specific reasons.

Having said that…if you want your own objects to cast and/or receive shadows, and your objects are not part of Rhino’s object database, then you must draw your object(s) from within the “middleground” channel. That means you must implement the “DrawObject()” conduit channel from within your own conduit (i.e. CSupportChannels::SC_DRAWOBJECT) and draw your object(s) there … Doing it within the PostDrawObjects() channel is just simply not going to work…and the actual name of the channel should be enough to understand why… “Post … Draw … Objects” … That means that channel gets executed AFTER all the objects have been drawn…in which case, if you’re drawing any kind of shaded mesh in that channel, how could it possibly participate in any kind of shadow casting or receiving phase, since everything has already been drawn?

Hope this is helps clear things up… If you are drawing your objects via the CSupportChannels::SC_DRAWOBJECT channel and things aren’t working as expected, then there’s a bug somewhere…and I’ll need a conduit example that I can compile and debug with.

Let me know if you have any questions or issues on this behavior…I’ll be glad to help.

Thanks,
-Jeff

Hi Jeff,

Thanks for the explanation, I understand that shadows cannot be computed on a “Post Draw” phase but as far as I understant neither in PreDrawObjects I’m quite new in Rhino development and I wouldn’t like to create a custom shader for that or intervene Rhino OpenGL pipeline explicitly due it’s a hard work… but if there is no other way I’ll do it., I was guessing if Rhino has any easier way to do it.

I’m writing this plugin in c# but I have no problem to write some parts in c++ and make a wrapper, I’ve found the DisplayConduit class which seems to be the equivalent for CRhinoDisplayConduit but I didn’t find the equivalence for CSupportChannels::SC_DRAWOBJECT or any way to draw there except overriding predraw, postdraw which doesn’t help to cast shadows, is that a c++ exclusive feature? or is it accesible from rhinocomon c# sdk? actually I’m a little bit lost…

Thanks.
Will

Hi Will,

It’s most likely that the DrawObject() channel hasn’t been put into RhinoCommon since it can become a severe overhead if/when not used properly… @dale would probably know more but @steve would definitely know why. I thought there was at least one “object based” channel available to C#… I want to say it’s PreDrawObject (note: the singular usage … i.e. NOT PreDrawObjects)… that is definitely confusing I realize…but one gets called just before an object is drawn (PreDrawObject), while the other gets called before ANY object gets draw (PreDrawObjects).

It’s starting to sound like we’re going to need yet another conduit channel (SC_SHADOWPASS) for this type of thing if DrawObject() will not be exposed… In either case, it doesn’t look like this can be done using C# at the moment…unless what I said above is true.

This small rundown of the pipeline might shed a little more light on conduits.

Thanks,
-Jeff

Hey Will…

I just realized that you’re talking about your own geometry that doesn’t exist anywhere… All of the “object-based” channels require some kind of reference geometry to work, otherwise, none of the object channels will ever be called.

I’m looking into why this hasn’t been setup to work in cases like yours…and scratching my head as to why we haven’t caught or heard of this problem up until now.

Stay tuned…
-Jeff

Hi Will,

This is clearly a bug and oversight on our part… Grasshopper objects work, so I guess we figured everything was working since it’s a plugin as well… But it turns out it works for very different reasons, which I will not go into here.

For now, this has been logged as a bug and you can track it here:

https://mcneel.myjetbrains.com/youtrack/issue/RH-54147

Thanks,
-Jeff

Hi Jeff,

Thank you to toke a look deeply, I appreciate it a lot, I’ll wait for a fix.
Thanks again.

William.