Udostępnij za pośrednictwem


Material Behavior

What Material you choose will impact your GeometryModel3D in three ways:

  1. Lighting model
  2. Depth write
  3. Blend with the back buffer

The first one is straightforward since it's right in the name of the Material plus it's documented. The last two aren't obvious at all and this is probably the first you've heard of them.

Type Depth Write Blend
DiffuseMaterial Yes SrcOver: SαS+(1-Sα)D
"AmbientMaterial" Yes SrcOver: SαS+(1-Sα)D
EmissiveMaterial No Additive: SαS+D
SpecularMaterial No Additive: SαS+D

Depth write and the depth buffer

If you haven't heard of the depth buffer (a.k.a. the z buffer) before, it's essentially how the card keeps track of the distance to an object from the camera per pixel. When a polygon is being rasterized at a pixel that has already been written to, do you keep the old value or take the new value? For opaque objects, you typically want the one closest to the camera to win because you won't be able to see the occluded one. This is what we tell the card to do (for you D3D programmers out there, we use D3DCMP_LESSEQUAL).

For example, say you draw a triangle with a DiffuseMaterial. If you then draw another triangle directly behind, it will be ignored in the area of overlap because the first triangle is in front of it. But if a polygon doesn't write to the depth buffer, then it's like the card doesn't know it's there. Say you draw a triangle with an EmissiveMaterial. If you then draw an overlapping triangle it doesn't matter if it's behind or in front -- the new triangle overwrites the old one because the card has no "record" of the old one.

Can you think of why the depth buffer might cause problems with transparent objects in a dynamic scene? That's a topic for another post :)

Blend

In the equation above, S means source (the GeometryModel3D you're drawing) and D means destination (what you've drawn to the back buffer already). From the equations you can make a few observations like a fully opaque DiffuseMaterial will never let you see what was previously written or even opaque additive Materials will appear transparent because they don't block out what is already there.

Why are there different behaviors?

The behaviors came out of how we think most people use Materials. Just about every Model3D will contain a DiffuseMaterial and will want to write to the depth buffer. If you then want your Model3D to glow or shine, you throw in an EmissiveMaterial or SpecularMaterial. Since you already wrote the depth, you don't need to do it again in the emissive and specular passes. Furthermore, you don't want emissive and specular to subtract away from the diffuse layer you just put down.

Extra Tips

"AmbientMaterial" is in quotes because it doesn't exist but you can make a Material that only responds to ambient light. See my earlier color knobs post.

If you'd like one of the additive Materials to write depth, you can do so by putting them in a MaterialGroup along with a transparent black DiffuseMaterial. That way the DiffuseMaterial doesn't affect the color but does affect the depth buffer. You can put this "depth pass" DiffuseMaterial before or after the other Materials but you will get different results between the two if you have any overlapping front faces (or back faces if we're talking about BackMaterial). 

-- Jordan

Comments

  • Anonymous
    July 23, 2007
    Just a quick post here - When making WPF 3D apps, transparency can make for some powerful visual effects.

  • Anonymous
    July 23, 2007
    Just a quick post here - When making WPF 3D apps, transparency can make for some powerful visual effects

  • Anonymous
    August 02, 2007
    Yesterday I posted a some screenshots of a 3D earth sample involving a mix of materials to achieve interesting

  • Anonymous
    June 15, 2009
    I have a poor English ability. made rounded rectangle that use diffusematerial , but that rectangles have a zorder(?) problem. A rect, B rect, Background A -> B -> Background Zorder Rounded(Transparent) area  A -> Background  ---> B is disapear. rounded corner border(canvas) have same problem. i want to your help. plz. ex pic)  http://jjacko.tistory.com/entry/WPF-Zorder-Rounded-Rectangle-Problem

  • Anonymous
    June 16, 2009
    You need to sort transparent DiffuseMaterials from back to front because DiffuseMaterial writes to the depth buffer. Peter talks about it more here: http://blogs.msdn.com/pantal/archive/2007/07/23/sorting-for-wpf-3d-transparency.aspx

  • Anonymous
    June 16, 2009
    Thank you Very veryvery much ArrayList list = new ArrayList();                foreach (Panel3D model in Panel)                {                    double Angle = Math.Abs(model.Angle / 360.00) > 180 ? 360 - model.Angle : model.Angle;                    list.Add(new ModelAngle(Angle, model));                }                list.Sort(new AngleComparer(SortDirection.FarToNear));                base.Children.Clear();                int n = 0;                foreach (ModelAngle modelAngle in list)                {                    base.Children.Add(modelAngle.model);                    (modelAngle.model as Panel3D).SetMouseEvent();                } i solved it , used  angle value. and have other problem. after modify mouse event does not work . anyway I appreciate your help.

  • Anonymous
    June 18, 2009
    I hinted at this a long time ago and then forgot to follow up, whoops! As the old post says, DiffuseMaterial